如何从Java中的剩余请求中检索客户端证书 [英] How to retrieve client certificate from rest request in Java

查看:81
本文介绍了如何从Java中的剩余请求中检索客户端证书的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将Jersey用于JavaJetty中的REST服务器作为Web服务器.我有self signed证书.我想从收到的HTTP请求中获取客户端证书详细信息.如何从HttpServletRequest获取信息?

I'm using Jersey for REST server in Java and Jetty as web server. I have self signed certificates. I want to fetch client certificate details from received HTTP Request. How to obtain the information from HttpServletRequest?

一种方法:

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

这是对的吗?这会导致异常,

Is this right? This results in exception,

Error [Ljava.lang.Object; cannot be cast to [Ljava.security.cert.X509Certificate 

我应该包括其他任何JAR吗?还是有什么方法可以获取客户端证书的详细信息?

Should I include any additional JAR? Or is there any way to obtain client certificate details?

我也遇到过

httpRequest.getHeader("ssl_client_cert");

这两种方式似乎都不适合我.如何获取详细信息?

Both ways not seems to work for me. How to get the details?

推荐答案

首先,确保您的处理SSL/TLS的ServerConnector. 接下来,该ServerConnector应该具有一个SslConnectionFactory,其中带有配置的HttpConfiguration对象. 该HttpConfiguration对象应该添加了SecureRequestCustomizer.

First, ensure that your ServerConnector that handles SSL/TLS. Next, that ServerConnector should have a SslConnectionFactory with a configured HttpConfiguration object within it. That HttpConfiguration object should have the SecureRequestCustomizer added to it.

用嵌入式码头的话来说,看起来像这样...

In embedded-jetty parlance, it looks like this ...

        // 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 ...

If you are using a ${jetty.home} and ${jetty.base} split on standalone Jetty, then you'll want to check that the jetty-ssl.xml is present in your configuration ...

$ 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

一旦您验证了此基本级别的配置,即使使用这些属性也可以使用.

Once you have verified this base level configuration you are good to go with even using those attributes.

接下来,当您向该安全连接器发出请求时,各种过滤器和servlet将有权访问许多可能对您有用的请求属性.

Next, when you make a request to that secure connector, the various filters and servlets will have access to a number of request attributes that could prove useful to you.

这些是Servlet规范定义的属性,已被SecureRequestCustomizer添加到传入的HttpServletRequest中.

These are the Servlet spec defined attributes that SecureRequestCustomizer adds to your incoming 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对象.
  • javax.servlet.request.X509Certificate holds an array of java.security.cert.X509Certificate objects.
  • javax.servlet.request.cipher_suite holds your negotiated cipher suite as a String object.
  • javax.servlet.request.key_size holds your keysize as an Integer object.
  • javax.servlet.request.ssl_session_id holds your SSL Session ID as a String object.

这些是SecureRequestCustomizer添加到传入的HttpServletRequest中的Jetty定制属性.

These are the Jetty custom attributes that SecureRequestCustomizer adds to your incoming HttpServletRequests.

  • org.eclipse.jetty.servlet.request.ssl_session保持该连接的活动java.net.ssl.SSLSession对象.
  • org.eclipse.jetty.servlet.request.ssl_session holds the active java.net.ssl.SSLSession object for this connection.

由于尝试使用该属性时看到的是通用Object[],因此也许应该调试并查看这些对象的实际含义.

Since you are seeing a generic Object[] from your attempt to use the attribute, perhaps you should debug and see what those objects actually are.

请考虑一下,在尝试访问它们之前,Jetty无法控制的某些东西可能已替换了它们,或者使它们无法在Servlet规格表中显示给Jetty.

Consider that something outside of Jetty's control might have replaced them, or made them unavailable to Jetty in the Servlet spec form before you attempted to access them.

  • 过去已知一些第三方安全性库会更改这些属性.
  • 或者您不是要在Jetty终止TLS/SSL连接,例如在防火墙/路由器/负载平衡器(haproxy,nginx,apache httpd或各种硬件)处终止(这意味着Jetty无法看到证书).
  • 您没有使用普通的ServerConnector(例如UnixSocketConnector,LocalConnector或自定义连接器)
  • 或者您在Java实现中有一个第三方安全层.
Object certs[] = httpRequest.getAttribute("javax.servlet.request.X509Certificate");
for(Object cert: certs) {
  System.out.printf("DEBUG: Cert[%s] = %s%n", cert.getClass().getName(), cert);
}

这篇关于如何从Java中的剩余请求中检索客户端证书的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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