如何使用HttpClient來發送帶客戶端證書的請求,以及如何忽略掉對服務器端證書的校驗

 最近要作客戶端和服務器端的雙向認證,在客戶端向服務器端發送帶證書的請求這裏有一點問題,網上的例子大多都不太好使,因而找了github上httpclient源代碼中的例子改造了一下,終於弄明白了java

github上我參考的例子在:https://github.com/apache/httpclient/blob/4.5.x/httpclient/src/examples/org/apache/http/examples/client/ClientCustomSSL.javagit

下面先貼上我本身的代碼(須要導入HttpClient等相關jar包),而後再說明github

 

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/*
 * Created with Intellij IDEA
 * USER: 焦一平
 * Date: 2016/5/8
 * Time: 1:10
 * To change this template use File | Settings | File Template
 */
public class SSLDemo {
    public static void main(String[] args) throws Exception {
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\jiaoyiping.p12")), "123456".toCharArray());
        SSLContext sslcontext = SSLContexts.custom()
                //忽略掉對服務器端證書的校驗
                .loadTrustMaterial(new TrustStrategy() {
                    @Override
                    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        return true;
                    }
                })
                
                //加載服務端提供的truststore(若是服務器提供truststore的話就不用忽略對服務器端證書的校驗了)
                //.loadTrustMaterial(new File("D:\\truststore.jks"), "123456".toCharArray(),
                //        new TrustSelfSignedStrategy())
                .loadKeyMaterial(keyStore, "cmcc".toCharArray())
                .build();
        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
                sslcontext,
                new String[]{"TLSv1"},
                null,
                SSLConnectionSocketFactory.getDefaultHostnameVerifier());
        CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLSocketFactory(sslConnectionSocketFactory)
                .build();

        try {

            HttpGet httpget = new HttpGet("https://10.2.5.116/PnsReceiver/ReceiveMessage");

            System.out.println("Executing request " + httpget.getRequestLine());

            CloseableHttpResponse response = httpclient.execute(httpget);
            try {
                HttpEntity entity = response.getEntity();
                System.out.println(response.getStatusLine());
                System.out.println(IOUtils.toString(entity.getContent()));
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    }
}

 

 

SSLContexts.custom() 方法返回一個 SSLContextBuilder實例,來構建SSLContext,下面是SSLContextBuilder的方法列表:

其中:
loadKeyMaterial()重載方法是加載客戶端證書用的
loadTrustMaterial()重載方法是加載服務器端相關信息用的(咱們就是使用 loadTrustMaterial(TrustStrategy trustStrategy) 方法本身實現了一個信任策略,不對服務器端的證書進行校驗),

在生成HttpClient的時候,指定相應的 SSLSocketFactory,以後,使用這個HttpClient發送的GET請求和POST請求就自動地附加上了證書信息

若是咱們只須要忽略掉對服務器端證書的驗證,而不須要發送客戶端證書信息,在構建SSLContext的時候,只須要 loadTrustMaterial() 不須要 loadKeyMaterial()

關於客戶端證書的類型問題:咱們導出的pfx或者P12後綴的文件都是pkcs12類型的,根據java的文檔,我找到了KeyStore支持的三種類型,以下圖:

客戶端如何只信任某個服務器端的證書信息 會在以後的文章中寫
相關文章
相關標籤/搜索