簡體   English   中英

如何從Java中的剩余請求中檢索客戶端證書

[英]How to retrieve client certificate from rest request in Java

我正在將Jersey用於JavaJetty REST服務器用作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不可用,然后再嘗試訪問它們。

  • 過去,已知一些第三方安全性庫會更改這些屬性。
  • 或者,您不是要在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);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM