我在Jersey
和REST
中使用Java
作为Jetty
服务器作为Web服务器。我有self signed
证书。我想从收到的HTTP请求中获取客户端证书详细信息。如何从HttpServletRequest
获取信息?
一种方法:
X509Certificate certs[] = (X509Certificate[])httpRequest.getAttribute("javax.servlet.request.X509Certificate");
这是正确的吗?这导致例外,
Error [Ljava.lang.Object; cannot be cast to [Ljava.security.cert.X509Certificate
我应该包括任何额外的JAR
吗?或者有没有办法获得客户证书详细信息?
我也遇到过,
httpRequest.getHeader("ssl_client_cert");
两种方式似乎都不适合我。如何获取详细信息?
首先,确保您的ServerConnector处理SSL / TLS。接下来,该ServerConnector应该有一个SslConnectionFactory,其中包含已配置的HttpConfiguration对象。该HttpConfiguration对象应该添加SecureRequestCustomizer。
在嵌入式码头的说法中,它看起来像......
// SSL Context Factory
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath("/path/to/keystore");
sslContextFactory.setKeyStorePassword("password");
sslContextFactory.setKeyManagerPassword("secret");
sslContextFactory.setTrustStorePath("/path/to/keystore");
sslContextFactory.setTrustStorePassword("password");
// SSL HTTP Configuration
HttpConfiguration https_config = new HttpConfiguration(http_config);
https_config.addCustomizer(new SecureRequestCustomizer()); // <-- THIS LINE
// SSL Connector
ServerConnector sslConnector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory,HttpVersion.HTTP_1_1.asString()),
new HttpConnectionFactory(https_config));
sslConnector.setPort(8443);
server.addConnector(sslConnector);
如果您在独立的Jetty上使用${jetty.home}
和${jetty.base}
分割,那么您需要检查配置中是否存在jetty-ssl.xml
...
$ cd /path/to/my-jetty-base
$ java -jar /path/to/jetty-home/start.jar --list-config
Java Environment:
-----------------
java.home = /Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/jre (null)
java.vm.vendor = Oracle Corporation (null)
java.vm.version = 25.202-b08 (null)
java.vm.name = Java HotSpot(TM) 64-Bit Server VM (null)
java.vm.info = mixed mode (null)
java.runtime.name = Java(TM) SE Runtime Environment (null)
java.runtime.version = 1.8.0_202-b08 (null)
java.io.tmpdir = /var/folders/w5/mmnzpk0n369dntp4nszlc8h40000gn/T/ (null)
user.dir = /path/to/my-jetty-base (null)
user.language = en (null)
user.country = US (null)
Jetty Environment:
-----------------
jetty.version = 9.4.15.v20190215
jetty.tag.version = master
jetty.home = /path/to/jetty-home
jetty.base = /path/to/my-jetty-base
...(snip lots of output)...
Jetty Active XMLs:
------------------
${jetty.home}/etc/jetty-threadpool.xml
${jetty.home}/etc/jetty.xml
${jetty.home}/etc/jetty-webapp.xml
${jetty.home}/etc/jetty-plus.xml
${jetty.home}/etc/jetty-annotations.xml
${jetty.home}/etc/jetty-deploy.xml
${jetty.home}/etc/jetty-http.xml
${jetty.home}/etc/jetty-ssl.xml <-- THIS LINE
${jetty.home}/etc/jetty-ssl-context.xml
${jetty.home}/etc/jetty-https.xml
${jetty.home}/etc/jetty-jaas.xml
${jetty.home}/etc/jetty-rewrite.xml
${jetty.base}/etc/demo-rewrite-rules.xml
${jetty.base}/etc/test-realm.xml
一旦验证了这个基本级别配置,即使使用这些属性,也可以使用。
接下来,当您向该安全连接器发出请求时,各种过滤器和servlet将可以访问许多可能对您有用的请求属性。
这些是Servlet规范定义的属性,SecureRequestCustomizer
为您的传入HttpServletRequest添加了这些属性。
javax.servlet.request.X509Certificate
拥有一系列java.security.cert.X509Certificate
物体。javax.servlet.request.cipher_suite
将您的协商密码套件保存为String
对象。javax.servlet.request.key_size
将你的密钥作为Integer
对象。javax.servlet.request.ssl_session_id
将您的SSL会话ID保存为String
对象。这些是SecureRequestCustomizer
为您的传入HttpServletRequests添加的Jetty自定义属性。
org.eclipse.jetty.servlet.request.ssl_session
为此连接保存活动的java.net.ssl.SSLSession
对象。由于您在尝试使用该属性时看到了通用的Object[]
,也许您应该调试并查看这些对象实际上是什么。
考虑Jetty控件之外的某些东西可能已经取代它们,或者在尝试访问它们之前使它们在Servlet规范表单中对Jetty不可用。
Object certs[] = httpRequest.getAttribute("javax.servlet.request.X509Certificate");
for(Object cert: certs) {
System.out.printf("DEBUG: Cert[%s] = %s%n", cert.getClass().getName(), cert);
}