Java 使用HttpClient 4.0.1与x509证书进行相互身份验证

Java 使用HttpClient 4.0.1与x509证书进行相互身份验证,java,authentication,httpclient,x509,Java,Authentication,Httpclient,X509,关于如何使用HTTPClient 4.0.1通过x509证书执行客户端身份验证,是否有人提供了一些友好的提示?以下是一些代码。KeyStore是包含客户端证书的对象。如果服务器使用的是自签名证书或未经JVM在包含的cacerts文件中识别的CA签名的证书,那么您将需要使用信任库。否则,要使用默认的cacerts文件,请将truststore参数的null传递到SSLSockeFactory import org.apache.http.conn.scheme.Scheme; import org

关于如何使用HTTPClient 4.0.1通过x509证书执行客户端身份验证,是否有人提供了一些友好的提示?

以下是一些代码。
KeyStore
是包含客户端证书的对象。如果服务器使用的是自签名证书或未经JVM在包含的cacerts文件中识别的CA签名的证书,那么您将需要使用
信任库
。否则,要使用默认的cacerts文件,请将truststore参数的
null
传递到
SSLSockeFactory

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);
另一个解决方案(从另一个示例复制)。我对“信任”(trustStore)和对自己进行身份验证(keystore)使用了相同的密钥库


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


非常感谢。我很快会查出来的。这个解决方案非常有效。谢谢你的帮助。仅供参考,由于SSL握手重新协商问题,我必须设置以下虚拟机属性:-Dsun.security.SSL.allowUnsafeRenegotiation=true我正在/正在使用java 1.6.0_20和tomcat 6.0.29。在使用jdk 1.6.0_24或更高版本时,不再需要上述注释。有关Apache HTTP客户端4.3+,请参阅Apache HTTP客户端4.4+,请参阅来自的@eviraat
 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();
 }
{
    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();
    }
}