29

我基本上正在寻找某个地方开始学习如何使用 java 与政府 CAC 卡进行交互。

最终,我的目标是找出如何使用 CAC 卡身份验证(通过 PIN 号)来授权访问使用 Tomcat/J2EE 服务器托管的网站。

但我需要从某个地方开始。所以我想我会先编写一个小型java程序来简单地从插入我键盘上的读卡器的CAC卡中读取CAC卡信息(DELL键盘,数字键盘上方有CAC读卡器)。

通过谷歌搜索,我找到了被OpenSSO项目取代的cacard java 项目(https://cacard.dev.java.net/ ) 。但我似乎找不到如何使用它连接到卡、从卡中读取等的示例代码。

有谁知道我在哪里可以找到一些示例代码,以便我可以开始学习如何使用 java 与 CAC 卡进行交互?

谢谢

编辑:

在研究了更多之后,我在想,我可以只clientAuth="true"server.xml文件中设置连接器元素吗?

http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html

clientAuth:如果您希望 Tomcat 要求所有 SSL 客户端提供客户端证书才能使用此套接字,请将此值设置为 true。

4

3 回答 3

16

您是在创建 Web 应用程序,还是尝试编写在客户端运行的软件(有点像您自己的 Web 浏览器)?

如果您正在创建一个 Web 应用程序,它几乎只是标准的客户端认证身份验证。证书来自硬件令牌这一事实对服务器而言并没有太大变化。如果您只想接受CAC 证书,您可以在服务器验证客户端证书时指定一组可接受的证书策略。(策略验证是 PKIX 验证的标准部分。)如果此应用程序是针对政府客户的,您需要与他们的安全团队密切合作,以确保您的解决方案满足他们的要求,这可能是严格的。如果这是您的情况,请告诉我,我会用我们遇到的一些问题更新我的答案。

如果您正在编写客户端,并且需要访问物理阅读器,则可以使用Sun PKCS #11 提供程序,从 Java 1.5 开始。我已经尝试过这个提供程序,你可以在另一个答案中阅读更多关于它的信息。


在服务器上,您应该检查证书是否未被吊销。然而,其中一些 CRL 非常庞大——我们有超过 100 Mb 的 CRL 文件,而内置的 Sun 撤销检查器无法很好地扩展到这个大小。

您还需要确保在 Tomcat 的“信任”密钥库中拥有正确的根 CA 证书(政府根 CA 证书更难找到,因为他们希望确保用户正确验证它们)。我们还发现,除非用户手动将中间证书导入浏览器,否则 Firefox 不会发送整个证书链。

于 2009-02-13T00:31:44.167 回答
9

您需要创建一个名为card.config并在其中包含以下行的文件:

name = myConfig
library = /path/to/library/that/implements/cac/card/reader 

然后试试这个:

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());
         }
      }
   }
}

此时,您有一个密钥库,可用于创建 ssl 套接字以与 https Web 服务器通信。

于 2009-10-27T18:48:53.287 回答
0

研究使用 SSO 类型应用程序(例如OpenSSOJOSSO )使用证书身份验证。代理应该更易于嵌入,并且他们已经实现了大部分细节。如果您需要自己做,他们也有很多与所需步骤相关的文档,例如:数字证书设置

于 2009-07-08T22:08:19.327 回答