`
阿尔萨斯
  • 浏览: 4147506 次
社区版块
存档分类
最新评论

JAVA通过servlet读IE端的证书即为什么老是得到null值的最终解决方案

 
阅读更多

更详细的内容参考我的另一篇:


网上交易安全之九阳神功-使用JAVA调用U盾进行客户认证的total solution


需要解决的问题:

1.Servlet如何读客户端的认证

很多网上的朋友都说

“我用X509Certificate[]certs = (X509Certificate[]) request .getAttribute("javax.servlet.request.X509Certificate");

得到的证书是个null”

几乎没有答案,这边给出解决方案

a.客户端访问这个servlet,客户端和放这个servlet的j2eeapp必须实现“双向认证”

b.J2ee app端(假设我们这边用TOMCAT实现),在实现双向认证后,其实还不够,需要加一个参数,很多人可能没注意到这个参数,下面给出方案:

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"

enableLookups="false"disableUploadTimeout="true"

useURIValidationHack="false"

scheme="https"secure="true"

keystoreFile="D:/tomcat/conf/shnlap93.jks"keystorePass="xxxxxxx"

truststoreFile="D:/tomcat/conf/truststore.jks"truststorePass="aaaaaa"

truststoreType="JKS"

clientAuth="true"sslProtocol="TLS" />

看到上面那个标红的地方了吧?就是这个参数没加,因此很多人就算启用了双向认证,你的servlet在拿ie端的证书时还是会得到null值

2.好,现在客户端的公钥拿到了,怎么拿私钥?

前面说了,我们先做一个简单的,写死的,就是把客户端的私钥放在我们的网站的某个目录下,然后用程序去读出来。

因此我们的过程如下:

a.客户端通过IE输入他的交易密码

b.然后点“提交”按钮,POST到我们的这个servlet

c.Servlet先读放在网站某个目录下的该客户的私钥,loadPrivateKey后用私钥对客户提交的form里的密码进行签名。

d.Servlet获得客户端IE里的证书,把公钥拿出来,然后用公钥对签完名的byte[]进行verify, 得到true代表认签成功,false认签失败,下面是我们的servlet

此处需要注意的是我们用openssl签出的private key是不能直接被java所访问的,因为它含用:

#begin certificate

#end certificate

这样的东西,而JAVA只认#begin…#end当中的那块东西,怎么办:

使用下面这条使用把openssl签出的key转成我们java可以认的rsa的KEY

opensslpkcs8 -topk8 -inform PEM -outform DER -in shnlap93.key -out pkcs8_der.key –nocrypt

下面是我们的servlet的核心片段, 拿客户端IE的公钥,拿网站某个目录摆放的私钥,然后调用标准的JAVA电子签名

private PublicKey getPubKeyFromIE(HttpServletRequest request,

HttpServletResponse response) throws ServletException, IOException {

System.out.println("...security receive done..." + request.getScheme());

String issue, after, before, subject;

String serialno, signalg;

int version;

String cipherSuite = "";

PublicKey pk = null;

try {

cipherSuite = (String) request

.getAttribute("javax.servlet.request.cipher_suite");

System.out.println("cipherSuite=====" + cipherSuite);

// response.setContentType("text/plain");

// FileInputStream fis = new FileInputStream("d://paramita.cer ");

PrintWriter out = response.getWriter();

if (cipherSuite != null) {

X509Certificate[] certs = (X509Certificate[]) request .getAttribute("javax.servlet.request.X509Certificate");

/* ibm http server us followings */

// X509Certificate[] certs = (X509Certificate[]) request

// .getAttribute("javax.net.ssl.peer_certificates");

if (certs != null) {

if (certs.length > 0) {

X509Certificate t = certs[0];

pk = t.getPublicKey();

}

} else {

if ("https".equals(request.getScheme())) {

out.println("This was an HTTPS request, "

+ "but no client certificate is available");

} else {

out.println("This was not an HTTPS request, "

+ "so no client certificate is available");

}

}

}

return pk;

} catch (Exception e) {

throw new ServletException(e);

}

}


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics