getAttribute("javax.servlet.request.X509Certificate") 未设置(Spring、CXF、Jetty、JAX-RSv1.1)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24351472/
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
getAttribute("javax.servlet.request.X509Certificate") not set (Spring,CXF,Jetty,JAX-RSv1.1)
提问by Jana Weschenfelder
My client implements Two-Way SSL in the following way:
我的客户通过以下方式实现双向 SSL:
private final static String KEYSTORE = "/security/client.jks"; private final static String KEYSTORE_PASSWORD = "secret"; private final static String KEYSTORE_TYPE = "JKS"; private final static String TRUSTSTORE = "/security/certificates.jks"; private final static String TRUSTSTORE_PASSWORD = "secret"; private final static String TRUSTSTORE_TYPE = "JKS"; ... KeyStore keystore = KeyStore.getInstance(KEYSTORE_TYPE); FileInputStream keystoreInput = new FileInputStream(new File(KEYSTORE)); keystore.load(keystoreInput, KEYSTORE_PASSWORD.toCharArray()); KeyStore truststore = KeyStore.getInstance(TRUSTSTORE_TYPE); FileInputStream truststoreIs = new FileInputStream(new File(TRUSTSTORE)); truststore.load(truststoreIs, TRUSTSTORE_PASSWORD.toCharArray()); SSLSocketFactory socketFactory = new SSLSocketFactory(keystore, KEYSTORE_PASSWORD, truststore); Scheme scheme = new Scheme("https", 8543, socketFactory); SchemeRegistry registry = new SchemeRegistry(); registry.register(scheme); ClientConnectionManager ccm = new PoolingClientConnectionManager(registry); httpclient = new DefaultHttpClient(ccm); HttpResponse response = null; HttpGet httpget = new HttpGet("https://mylocalhost.com:8543/test"); response = httpclient.execute(httpget); ...
And I try to retrieve the X.509 certificate on the server's side from the client via javax.servlet.http.HttpServletRequest.getAttribute("javax.servlet.request.X509Certificate") as it is decribed here: http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/ServletRequest.html#getAttribute%28java.lang.String%29.
我尝试通过 javax.servlet.http.HttpServletRequest.getAttribute("javax.servlet.request.X509Certificate") 从客户端检索服务器端的 X.509 证书,因为它在此处描述:http://tomcat。 apache.org/tomcat-5.5-doc/servletapi/javax/servlet/ServletRequest.html#getAttribute%28java.lang.String%29。
I get the HttpServletRequest on the server's side via:
HttpServletRequest servletRequest = (HttpServletRequest) msg.get("HTTP.REQUEST"); via the handleMessage(Message msg) method of my interceptor class which extends AbstractPhaseInterceptor<Message>. I have to use JAX-RS 1.1.1 on the server's side because of some Maven dependencies which I am not allowed to change and so I cannot use ContainerRequestFilter (supported from JAX-RS 2.0 on).
我通过以下方式在服务器端获取 HttpServletRequest:
HttpServletRequest servletRequest = (HttpServletRequest) msg.get("HTTP.REQUEST"); 通过我的拦截器类的 handleMessage(Message msg) 方法,它扩展了 AbstractPhaseInterceptor<Message>。我必须在服务器端使用 JAX-RS 1.1.1,因为我不允许更改某些 Maven 依赖项,因此我不能使用 ContainerRequestFilter(从 JAX-RS 2.0 开始支持)。
My problem is that getAttribute("javax.servlet.request.X509Certificate") on the server's side returns null all the time. If I verify the traffic between server and client, I can see that the certificate from the server is sent to the client, that handshake works. But I cannot see that the client certificate is sent to the server and I think it is the reason why getAttribute("javax.servlet.request.X509Certificate")
returns null
. Does someone know how I can solve that problem? I tried some other implementations on the client's side already, but with no change.
我的问题是服务器端的 getAttribute("javax.servlet.request.X509Certificate") 一直返回 null。如果我验证服务器和客户端之间的流量,我可以看到来自服务器的证书发送到客户端,握手有效。但是我看不到客户端证书被发送到服务器,我认为这是getAttribute("javax.servlet.request.X509Certificate")
返回null
. 有人知道我该如何解决这个问题吗?我已经在客户端尝试了一些其他实现,但没有任何变化。
What am I doing wrong? Many thanks in advance!
我究竟做错了什么?提前谢谢了!
Additional information: I have seen on the server's side that javax.servlet.request.ssl_session_id, javax.servlet.request.key_size and javax.servlet.request.cipher_suite are set, but the key javax.servlet.request.X509Certificate is not set. I'm using Jetty Server 8.1.15, Apache CXF 2.7.x and JAX-RS 1.1.1. I tried with Jetty configuration via http://cxf.apache.org/docs/jetty-configuration.htmland http://cxf.apache.org/docs/secure-jax-rs-services.html#SecureJAX-RSServices-Configuringendpoints, the attribute still isn't set.
附加信息:我在服务器端看到设置了 javax.servlet.request.ssl_session_id、javax.servlet.request.key_size 和 javax.servlet.request.cipher_suite,但是没有设置密钥 javax.servlet.request.X509Certificate . 我使用的是 Jetty Server 8.1.15、Apache CXF 2.7.x 和 JAX-RS 1.1.1。我尝试通过http://cxf.apache.org/docs/jetty-configuration.html和http://cxf.apache.org/docs/secure-jax-rs-services.html#SecureJAX-RSServices-进行 Jetty 配置配置端点,该属性仍未设置。
回答by Jana Weschenfelder
Problem is solved. It wasn't a problem in the code, it was a certificate problem only. My problem was that I was a beginner regarding X509 certificates as well, it was a handshake problem between server and client. In this case, only the SSL/Handshake debug helped me. The debug log told that the server only accepted client certificates from a specific CA, the server told the client the required CA in a certificate request during the ServerHello message. Since the Client didn't have a certificate from that CA, it didn't send something and the connection between client and server was closed then, with the result that javax.servlet.request.X509Certificate was not set.
问题解决了。这不是代码问题,只是证书问题。我的问题是我也是 X509 证书的初学者,这是服务器和客户端之间的握手问题。在这种情况下,只有 SSL/Handshake 调试对我有帮助。调试日志告诉服务器只接受来自特定 CA 的客户端证书,服务器在 ServerHello 消息期间在证书请求中告诉客户端所需的 CA。由于客户端没有来自该 CA 的证书,它没有发送任何内容,客户端和服务器之间的连接随即关闭,结果 javax.servlet.request.X509Certificate 未设置。
For all others who might join the same problem sometime (which seems to be a common SSL configuration problem regarding to IBM as it is mentioned in the first link below), the following sources helped me a lot:
- http://www-01.ibm.com/support/docview.wss?uid=swg27038122&aid=1(pages 16 and 17)
- http://java.dzone.com/articles/how-analyze-java-ssl-errors(shows as the handshake should look)
- need help Debugging SSL handshake in tomcat(shows how to debug ssl errors in Java)
- https://thomas-leister.de/internet/eigene-openssl-certificate-authority-ca-erstellen-und-zertifikate-signieren/(in German, but maybe you can find an English equivalent)
- https://access.redhat.com/site/documentation/en-US/Red_Hat_JBoss_Fuse/6.0/html/Web_Services_Security_Guide/files/i382674.html(continuation of the German article)
- http://www.webfarmr.eu/2010/04/import-pkcs12-private-keys-into-jks-keystores-using-java-keytool/(how to create keystore and truststore)
对于有时可能会遇到相同问题的所有其他人(这似乎是 IBM 的常见 SSL 配置问题,因为它在下面的第一个链接中提到),以下来源对我帮助很大:
- http://www-01 .ibm.com/support/docview.wss?uid=swg27038122&aid=1(第 16 和 17 页)
- http://java.dzone.com/articles/how-analyze-java-ssl-errors(显示为握手应该看)
-需要帮助在 tomcat 中调试 SSL 握手(显示如何在 Java 中调试 ssl 错误)
- https://thomas-leister.de/internet/eigene-openssl-certificate-authority-ca-erstellen-und-zertifikate-signieren /(德语,但也许您可以找到等效的英语)
-https://access.redhat.com/site/documentation/en-US/Red_Hat_JBoss_Fuse/6.0/html/Web_Services_Security_Guide/files/i382674.html(德语文章的续篇)
- http://www.webfarmr.eu/2010 /04/import-pkcs12-private-keys-into-jks-keystores-using-java-keytool/(如何创建密钥库和信任库)
After creating an own CA, a server and client certificate and after creating the keystore and truststore for both, the attribute was set now:
- Here15_1: javax.servlet.request.X509Certificate
- Here16_2: class [Ljava.security.cert.X509Certificate;
- Here16_3: [Ljava.security.cert.X509Certificate;@43b8f002
The server code is able to extract the client certificate information now, too.
创建自己的 CA、服务器和客户端证书并为两者创建密钥库和信任库后,现在设置属性:
- Here15_1: javax.servlet.request.X509Certificate
- Here16_2: class [Ljava.security.cert.X509Certificate;
- Here16_3: [Ljava.security.cert.X509Certificate;@43b8f002
服务器代码现在也可以提取客户端证书信息了。