在 Servlet 中读取客户端证书 [英] Reading Client Certificate in Servlet

查看:27
本文介绍了在 Servlet 中读取客户端证书的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 JBOSS 和浏览器中有一个客户端服务器通信场景作为客户端(JAVA 程序).最初建立连接时,客户端将其证书发送到服务器.服务器从证书中提取客户端的公钥,从而继续通信.
现在我的问题是
如何从客户端向服务器发送证书(.cer)?
如何在Server中接收证书并提取其公钥?

I have a Client Server Communication scenario in JBOSS and browser as client(JAVA PROGRAM). Initially when the connection is made, Client sends its Certificate to Server. Server extracts the public key of client from certificate and thus communication will continue.
Now my question is
How to send certificate(.cer) from Client to Server?
How to receive the certificate and extract its public key in Server?

推荐答案

如何从客户端向服务器发送证书(.cer)?

客户端证书(.cer、.crt、.pem)及其对应的私钥(.key)应首先打包到 PKCS#12(.p12、.pfx)或 JKS(.jks)容器(keystore)中.您还应该将服务器的 CA 证书打包为 JKS(信任库).

Client certificate (.cer, .crt, .pem) and it's corresponding private key (.key) should be packaged into PKCS#12 (.p12, .pfx) or JKS (.jks) container first (keystore). You also should have server's CA certicate packaged as JKS (truststore).

使用 HttpClient 3.x 的示例:

HttpClient client = new HttpClient();
// truststore
KeyStore trustStore = KeyStore.getInstance("JKS", "SUN");
trustStore.load(TestSupertype.class.getResourceAsStream("/client-truststore.jks"), "amber%".toCharArray());
String alg = KeyManagerFactory.getDefaultAlgorithm();
TrustManagerFactory fac = TrustManagerFactory.getInstance(alg);
fac.init(trustStore);
// keystore
KeyStore keystore = KeyStore.getInstance("PKCS12", "SunJSSE");
keystore.load(X509Test.class.getResourceAsStream("/etomcat_client.p12"), "etomcat".toCharArray());
String keyAlg = KeyManagerFactory.getDefaultAlgorithm();
KeyManagerFactory keyFac = KeyManagerFactory.getInstance(keyAlg);
keyFac.init(keystore, "etomcat".toCharArray());
// context
SSLContext ctx = SSLContext.getInstance("TLS", "SunJSSE");
ctx.init(keyFac.getKeyManagers(), fac.getTrustManagers(), new SecureRandom());
SslContextedSecureProtocolSocketFactory secureProtocolSocketFactory = new SslContextedSecureProtocolSocketFactory(ctx);
Protocol.registerProtocol("https", new Protocol("https", (ProtocolSocketFactory) secureProtocolSocketFactory, 8443));
// test get
HttpMethod get = new GetMethod("https://127.0.0.1:8443/etomcat_x509");
client.executeMethod(get);
// get response body and do what you need with it
byte[] responseBody = get.getResponseBody();

您可以在这个项目中找到工作示例,请参阅X509Test 类.

You may find working example in this project see X509Test class.

使用 HttpClient 4.x 配置和语法会略有不同:

With HttpClient 4.x configuration and syntax would be slightly different:

HttpClient httpclient = new DefaultHttpClient();
// truststore
KeyStore ts = KeyStore.getInstance("JKS", "SUN");
ts.load(PostService.class.getResourceAsStream("/truststore.jks"), "amber%".toCharArray());
// if you remove me, you've got 'javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated' on missing truststore
if(0 == ts.size()) throw new IOException("Error loading truststore");
// tmf
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ts);
// keystore
KeyStore ks = KeyStore.getInstance("PKCS12", "SunJSSE");
ks.load(PostService.class.getResourceAsStream("/" + certName), certPwd.toCharArray());
// if you remove me, you've got 'javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated' on missing keystore
if(0 == ks.size()) throw new IOException("Error loading keystore");
// kmf
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, certPwd.toCharArray());
// SSL
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
// socket
SSLSocketFactory socketFactory = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Scheme sch = new Scheme("https", 8443, socketFactory);
httpclient.getConnectionManager().getSchemeRegistry().register(sch);
// request
HttpMethod get = new GetMethod("https://localhost:8443/foo");
client.executeMethod(get);
IOUtils.copy(get.getResponseBodyAsStream(), System.out);

如何在Server中接收证书并提取其公钥?

您的服务器必须配置为要求 X.509 客户端证书身份验证.然后在 SSL 握手期间,servlet 容器将接收证书,根据 trustore 进行检查并将其作为请求属性提供给应用程序.通常情况下,在单个证书的情况下,您可以在 servlet 环境中使用此方法来提取证书:

You server must be configurated to require X.509 client certificate authentication. Then during SSL handshake servlet container will recieve certificate, check it against trustore and provide it to application as a request attribute. In usual case with single certificate you could use this method in servlet environment to extract certificate:

protected X509Certificate extractCertificate(HttpServletRequest req) {
    X509Certificate[] certs = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
    if (null != certs && certs.length > 0) {
        return certs[0];
    }
    throw new RuntimeException("No X.509 client certificate found in request");
}

这篇关于在 Servlet 中读取客户端证书的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆