使用 Java 的通用访问卡 (CAC) 身份验证
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/544056/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Common Access Card (CAC) Authentication Using Java
提问by
I'm bascially looking for someplace to start learning how to interface with a government CAC card using java.
我正在寻找一些地方开始学习如何使用 java 与政府 CAC 卡进行交互。
Ultimately, my goal is to find out how to use CAC card authentication (by PIN number) to authorize access to a website hosted using a Tomcat/J2EE server.
最终,我的目标是找出如何使用 CAC 卡身份验证(通过 PIN 码)来授权访问使用 Tomcat/J2EE 服务器托管的网站。
But I'll need somewhere to start. So I figure I'd start by writing a small java program to simply read the CAC card information from the CAC card which is inserted into a card reader on my keyboard (DELL keyboard with CAC reader above the numeric keypad).
但我需要一个地方开始。所以我想我会首先编写一个小的java程序来简单地从CAC卡中读取CAC卡信息,该卡插入我的键盘上的读卡器(数字键盘上方带有CAC读卡器的戴尔键盘)。
By searching google, I found the cacardjava project (https://cacard.dev.java.net/) which was replaced by the OpenSSOproject. But I can't seem to find sample code of how to use it to connect to a card, read from a card, etc.
通过谷歌搜索,我找到了被OpenSSO项目取代的cacardjava 项目(https://cacard.dev.java.net/)。但我似乎找不到如何使用它来连接卡、从卡读取等的示例代码。
Does anyone know where I can find some sample code so that I can start learning how to interact with a CAC card using java?
有谁知道我在哪里可以找到一些示例代码,以便我可以开始学习如何使用 java 与 CAC 卡交互?
Thanks
谢谢
EDIT:
编辑:
After researching more, I was thinking, would I be able to just set clientAuth="true"
in the connector element in the server.xml
file?
在研究了更多之后,我在想,我是否可以只clientAuth="true"
在server.xml
文件中的连接器元素中进行设置?
http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html
http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html
clientAuth: Set this value to true if you want Tomcat to require all SSL clients to present a client Certificate in order to use this socket.
clientAuth:如果您希望 Tomcat 要求所有 SSL 客户端提供客户端证书才能使用此套接字,请将此值设置为 true。
回答by erickson
Are you creating the web application, or trying to write software that runs at the client (sort of like your own web browser)?
您是在创建 Web 应用程序,还是尝试编写在客户端运行的软件(有点像您自己的 Web 浏览器)?
If you are creating a web application, it's pretty much just standard client certification authentication. The fact that the certificate came from a hardware token doesn't change much for the server; if you want to accept onlyCAC certificates, you can specify set of acceptable certificate policies when the server validates the client certificate. (Policy validation is a standard part of PKIX validation.) If this application is for a government customer, you'll need to work closely with their security team to ensure that your solution meets their requirements, which can be stringent. If this is your scenario, let me know and I'll update my answer with some of the issues that we encountered.
如果您正在创建 Web 应用程序,它几乎只是标准的客户端认证身份验证。证书来自硬件令牌这一事实对服务器没有太大变化;如果你想接受只CAC证书,可以在服务器验证客户端证书规定了可接受的证书策略的设置。(策略验证是 PKIX 验证的标准部分。)如果此应用程序面向政府客户,则您需要与他们的安全团队密切合作,以确保您的解决方案满足他们的严格要求。如果这是您的情况,请告诉我,我会用我们遇到的一些问题更新我的答案。
If you are writing a client, and need to access the physical reader, you may be able to use the Sun PKCS #11 provider, since Java 1.5. I've experimented with this provider, and you can read more about it in another answer.
如果您正在编写客户端,并且需要访问物理阅读器,您可以使用Sun PKCS #11 provider,自 Java 1.5 起。我已经尝试过这个提供者,你可以在另一个答案中阅读更多关于它的信息。
On the server, you should check that the certificate is not revoked. However, some of these CRLs are enormous—we had over 100 Mb worth of CRL files, and the built-in Sun revocation checker does not scale well to this size.
在服务器上,您应该检查证书是否未被吊销。然而,其中一些 CRL 是巨大的——我们有超过 100 Mb 的 CRL 文件,并且内置的 Sun 吊销检查器不能很好地扩展到这个大小。
You will also need to make sure that you have the right root CA certificates in Tomcat's "trust" key store (the government root CA certs are little harder to find because they want to make sure users are verifying them properly). We also found that Firefox does not send the entire certificate chain unless users import the intermediate certificates into their browser manually.
您还需要确保在 Tomcat 的“信任”密钥库中拥有正确的根 CA 证书(政府根 CA 证书不太难找到,因为它们要确保用户正确验证它们)。我们还发现,除非用户手动将中间证书导入浏览器,否则 Firefox 不会发送整个证书链。
回答by Joshua
Look into using cert authentication using an SSO type application such as OpenSSOor JOSSO. The agent should be simpler to embed, and they have already implemented most of the details. If you need to do it yourself, they also have a lot of documentation related to the steps needed such as: digital certificates setup
考虑使用 SSO 类型的应用程序(例如OpenSSO或JOSSO )使用证书身份验证。代理应该更容易嵌入,他们已经实现了大部分细节。如果您需要自己动手,他们还有很多与所需步骤相关的文档,例如:数字证书设置
回答by Jay
You need to create a file called card.config
and include the following lines in it:
您需要创建一个名为的文件card.config
并在其中包含以下几行:
name = myConfig
library = /path/to/library/that/implements/cac/card/reader
And then try this:
然后试试这个:
import java.io.*;
import java.util.*;
import java.security.cert.CertificateException;
import java.security.KeyStoreException;
import java.security.cert.X509Certificate;
import java.security.KeyStore;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.Security;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
public class Test
{
public static void main(String arg[]) throws Exception
{
try
{
//Create our certificates from our CAC Card
String configName = "card.config";
Provider p = new sun.security.pkcs11.SunPKCS11(configName);
Security.addProvider(p);
//Get the pin from user entered data
Console c = System.console();
char[] pin = c.readPassword("Enter your PIN: ");
KeyStore cac = null;
cac = KeyStore.getInstance("PKCS11");
cac.load(null, pin);
showInfoAboutCAC(cac);
}
catch(Exception ex)
{
//System.out.println("*" + ex.getMessage());
ex.printStackTrace();
System.exit(0);
}
}
public static void showInfoAboutCAC(KeyStore ks) throws KeyStoreException, CertificateException
{
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements())
{
String alias = aliases.nextElement();
X509Certificate[] cchain = (X509Certificate[]) ks.getCertificateChain(alias);
System.out.println("Certificate Chain for : " + alias);
for (int i = 0; i < cchain.length; i ++)
{
System.out.println(i + " SubjectDN: " + cchain[i].getSubjectDN());
System.out.println(i + " IssuerDN: " + cchain[i].getIssuerDN());
}
}
}
}
At this point you have a keystore that you can use to create the ssl socket to talk to the https web server.
此时,您有一个密钥库,可用于创建 ssl 套接字以与 https Web 服务器通信。