【问题标题】:Mutual Authentication with x509 Certificates using HttpClient 4.0.1使用 HttpClient 4.0.1 与 x509 证书的相互身份验证
【发布时间】:2011-03-23 10:52:05
【问题描述】:

是否有人对如何使用 HTTPClient 4.0.1 通过 x509 证书执行客户端身份验证有任何友好的提示?

【问题讨论】:

    标签: java authentication httpclient x509


    【解决方案1】:

    这里有一些代码可以帮助你。 KeyStore 是包含客户端证书的对象。如果服务器正在使用自签名证书或未由 CA 签名的证书(在包含的 cacerts 文件中被 JVM 识别),那么您将需要使用 TrustStore。否则,要使用默认的 cacerts 文件,请将 null 传递给 SSLSockeFactory 作为 truststore 参数。

    import org.apache.http.conn.scheme.Scheme;
    import org.apache.http.conn.scheme.SchemeRegistry;
    import org.apache.http.conn.ssl.SSLSocketFactory;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
    import org.apache.http.params.BasicHttpParams;
    import org.apache.http.params.HttpParams;
    
    ...
    
    final HttpParams httpParams = new BasicHttpParams();
    
    // load the keystore containing the client certificate - keystore type is probably jks or pkcs12
    final KeyStore keystore = KeyStore.getInstance("pkcs12");
    InputStream keystoreInput = null;
    // TODO get the keystore as an InputStream from somewhere
    keystore.load(keystoreInput, "keystorepassword".toCharArray());
    
    // load the trustore, leave it null to rely on cacerts distributed with the JVM - truststore type is probably jks or pkcs12
    KeyStore truststore = KeyStore.getInstance("pkcs12");
    InputStream truststoreInput = null;
    // TODO get the trustore as an InputStream from somewhere
    truststore.load(truststoreInput, "truststorepassword".toCharArray());
    
    final SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme("https", new SSLSocketFactory(keystore, keystorePassword, truststore), 443));
    
    final DefaultHttpClient httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager(httpParams, schemeRegistry), httpParams);
    

    【讨论】:

    • 谢谢。我会尽快检查的。
    • 这个解决方案效果很好。谢谢您的帮助。仅供参考,由于 SSL 握手重新协商问题,我不得不设置以下虚拟机属性:-Dsun.security.ssl.allowUnsafeRenegotiation=true 我正在/正在使用 java 1.6.0_20 和 tomcat 6.0.29。
    • 使用 jdk 1.6.0_24 或更高版本时不再需要上述注释。
    • 对于 Apache HTTP 客户端 4.3+,请参阅 stackoverflow.com/a/26159543/340290
    • 对于 Apache HTTP 客户端 4.4+,请参阅 stackoverflow.com/a/38313344/340290
    【解决方案2】:

    另一种解决方案(复制自另一个示例)。我为“信任”(trustStore)和验证自己(keyStore)使用了相同的密钥库。

     KeyStore trustStore  = KeyStore.getInstance(KeyStore.getDefaultType());
     FileInputStream instream = new FileInputStream(new File("miller.keystore"));
     try {
         trustStore.load(instream, "pw".toCharArray());
     } finally {
         instream.close();
     }
    
     SSLContext sslcontext = SSLContexts.custom()
             .loadTrustMaterial(trustStore) /* this key store must contain the certs needed & trusted to verify the servers cert */
             .loadKeyMaterial(trustStore, "pw".toCharArray()) /* this keystore must contain the key/cert of the client */
             .build();
    
     SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,
             SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
     CloseableHttpClient httpclient = HttpClients.custom()
             .setSSLSocketFactory(sslsf)
             .build();
     try {
    
         HttpGet httpget = new HttpGet("https://localhost");
    
         System.out.println("executing request" + httpget.getRequestLine());
    
         CloseableHttpResponse response = httpclient.execute(httpget);
         try {
             HttpEntity entity = response.getEntity();
    
             System.out.println("----------------------------------------");
             System.out.println(response.getStatusLine());
             if (entity != null) {
                 System.out.println("Response content length: " + entity.getContentLength());
             }
             EntityUtils.consume(entity);
         } finally {
             response.close();
         }
     } finally {
         httpclient.close();
     }
    

    【讨论】:

      【解决方案3】:

      我使用了 HttpClient 网站上的示例代码中的以下内容(如果我没记错的话,自定义 SSL 上下文)。

      {
          KeyStore keyStore = KeyStore.getInstance("PKCS12"); //client certificate holder
          FileInputStream instream = new FileInputStream(new File(
                  "client-p12-keystore.p12"));
          try {
              trustStore.load(instream, "password".toCharArray());
          } finally {
              instream.close();
          }
      
          // Trust own CA and all self-signed certs
          SSLContext sslcontext = SSLContexts.custom()
                  .loadKeyMaterial(keyStore, "password".toCharArray())
                  // .loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()) //if you have a trust store
                  .build();
          // Allow TLSv1 protocol only
          SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                  sslcontext, new String[] { "TLSv1" }, null,
                  SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
          CloseableHttpClient httpclient = HttpClients
                  .custom()
                  .setHostnameVerifier(
                          SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER) //todo
                  .setSSLSocketFactory(sslsf).build();
          try {
      
              HttpGet httpget = new HttpGet("https://localhost:8443/secure/index");
      
              System.out.println("executing request" + httpget.getRequestLine());
      
              CloseableHttpResponse response = httpclient.execute(httpget);
              try {
                  HttpEntity entity = response.getEntity();
      
                  System.out.println("----------------------------------------");
                  System.out.println(response.getStatusLine());
                  if (entity != null) {
                      System.out.println("Response content length: "
                              + entity.getContentLength());
                  }
                  EntityUtils.consume(entity);
              } finally {
                  response.close();
              }
          } finally {
              httpclient.close();
          }
      }
      
      猜你喜欢
      • 1970-01-01
      • 2019-01-03
      • 1970-01-01
      • 2014-05-01
      • 2019-07-17
      • 2017-03-31
      • 2013-12-07
      • 2016-03-26
      • 1970-01-01
      相关资源
      最近更新 更多