2013年12月3日 星期二

使用 Apache HttpClient 4.3 發送 HTTPS 要求時略過所有認證檢查

一般正常在發送 HTTPS 要求時,必須先匯入伺服器的認證,才能正常建立 HTTPS 的加密連線
但某些狀況下,伺服器使用自我認證等等的方式時,會想要略過這些認證檢查(把 HTTPS 當成 HTTP 在使用...XD)
在 Apache HttpClient 4.3 當中可以用以下的方式取得 HTTPS 的連線。

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;

public static CloseableHttpClient getHttpClient() {
  SSLContextBuilder builder = new SSLContextBuilder();
  try {
    builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
    SSLConnectionSocketFactory sslsf = 
        new SSLConnectionSocketFactory(builder.build(), new X509HostnameVerifier() {
          @Override
          public boolean verify(String arg0, SSLSession arg1) { return true; }
          @Override
          public void verify(String arg0, SSLSocket arg1) throws IOException {}
          @Override
          public void verify(String arg0, X509Certificate arg1) throws SSLException {}
          @Override
          public void verify(String arg0, String[] arg1, String[] arg2) throws SSLException {}
        });
    return HttpClients.custom().setSSLSocketFactory(sslsf).build();
  } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
    e.printStackTrace();
    throw new RuntimeException();
  }
}

其中 5~6 行在某些狀況下應該可以直接用以下的方式:
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
只是我的測試環境中,似乎有 host name 無法正確驗證的問題,因此就加上了 20-29 行的程式碼,讓它一律不檢查 host name。

透過上面的 getHttpClient() 的方法取得 CloseableHttpClient 這個 HttpClient 後
就可以依照一般的方法進行 HTTPS 的連線了。

參考資料:
1、Ignoring SSL certificate in Apache HttpClient 4.3

沒有留言: