1. 程式人生 > >HttpClient忽略使用者證書驗證的方法

HttpClient忽略使用者證書驗證的方法

    程式中出了這樣的異常:javax.net.ssl.SSLException: hostname in certificate didn't match。異常發生在這行程式碼上:httpClient.execute(httpGet); 初步判斷是證書的問題,準備採用忽略證書的方法解決,但在網上找了半天都沒找到靠譜的程式碼解決,最後還是自己琢磨解決了。     得到一個教訓,網上找答案是不靠譜的,因為具體問題需要具體分析,別人的方法不一定能解決你的,一定要自己思考,自己琢磨。在網上最重要的是能找到問題的解決思路,最後還是要自己去思考解決自己問題的具體程式碼實現。     最後吐槽一句,網上的解決方法大多都是廢話一籮筐,半天說不到核心解決方法上。

核心思路:繼承SSLSocketFactory,重寫一個驗證證書時總是返回true的UnVerifySocketFactory,  * new一個這樣的UnVerifySocketFactory物件設定到httpclient上就行了.程式碼如下:

  1. import java.io.IOException;
  2. import java.net.Socket;
  3. import java.net.UnknownHostException;
  4. import java.security.KeyManagementException;
  5. import java.security.KeyStore;
  6. import java.security.KeyStoreException;
  7. import java.security.NoSuchAlgorithmException;
  8. import java.security.UnrecoverableKeyException;
  9. import java.security.cert.CertificateException;
  10. import java.security.cert.X509Certificate;
  11. import javax.net.ssl.SSLContext;
  12. import javax.net.ssl.SSLException;
  13. import javax.net.ssl.SSLSession;
  14. import javax.net.ssl.SSLSocket;
  15. import javax.net.ssl.TrustManager;
  16. import javax.net.ssl.X509TrustManager;
  17. import org.apache.http.HttpVersion;
  18. import org.apache.http.client.HttpClient;
  19. import org.apache.http.conn.ClientConnectionManager;
  20. import org.apache.http.conn.scheme.PlainSocketFactory;
  21. import org.apache.http.conn.scheme.Scheme;
  22. import org.apache.http.conn.scheme.SchemeRegistry;
  23. import org.apache.http.conn.ssl.SSLSocketFactory;
  24. import org.apache.http.conn.ssl.X509HostnameVerifier;
  25. import org.apache.http.impl.client.DefaultHttpClient;
  26. import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
  27. import org.apache.http.params.BasicHttpParams;
  28. import org.apache.http.params.HttpParams;
  29. import org.apache.http.params.HttpProtocolParams;
  30. import org.apache.http.protocol.HTTP;
  31. import android.util.Log;
  32. /**
  33. * 工具類:建立一個忽略使用者證書驗證的httpClient例項
  34. * @date 2015-02-13
  35. * @author Barry
  36. */
  37. public class CertificateValidationIgnored {
  38. public static HttpClient getNoCertificateHttpClient(String url){
  39. return getCertificateValidationIgnoredHttpClient();
  40. }
  41. private static HttpClient getCertificateValidationIgnoredHttpClient() {
  42. try {
  43. KeyStore trustStore = KeyStore.getInstance(KeyStore
  44. .getDefaultType());
  45. trustStore.load(null, null);
  46. //核心程式碼,建立一個UnVerifySocketFactory物件,驗證證書時總是返回true
  47. SSLSocketFactory sf = new UnVerifySocketFactory(trustStore);
  48. HttpParams params = new BasicHttpParams();
  49. HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
  50. HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
  51. SchemeRegistry registry = new SchemeRegistry();
  52. registry.register(new Scheme("http", PlainSocketFactory
  53. .getSocketFactory(), 80));
  54. registry.register(new Scheme("https", sf, 443));
  55. ClientConnectionManager ccm = new ThreadSafeClientConnManager(
  56. params, registry);
  57. return new DefaultHttpClient(ccm, params);
  58. } catch (Exception e) {
  59. Log.d("CertificateValidationIgnored", "建立忽略使用者證書的HttpClient物件失敗,嘗試建立普通HttpClient物件");
  60. e.printStackTrace();
  61. return new DefaultHttpClient();
  62. }
  63. }
  64. /**
  65. * 核心類
  66. * UnVerifySocketFactory:一個驗證證書時總是返回true的SSLSocketFactory的子類
  67. */
  68. private static X509HostnameVerifier ignoreVerifier;
  69. private static class UnVerifySocketFactory extends SSLSocketFactory {
  70. SSLContext sslContext = SSLContext.getInstance("TLS");
  71. public UnVerifySocketFactory(KeyStore truststore)
  72. throws NoSuchAlgorithmException, KeyManagementException,
  73. KeyStoreException, UnrecoverableKeyException {
  74. super(truststore);
  75. TrustManager tm = new X509TrustManager() {
  76. public void checkClientTrusted(X509Certificate[] chain,
  77. String authType) throws CertificateException {
  78. }
  79. public void checkServerTrusted(X509Certificate[] chain,
  80. String authType) throws CertificateException {
  81. }
  82. public X509Certificate[] getAcceptedIssuers() {
  83. return null;
  84. }
  85. };
  86. sslContext.init(null, new TrustManager[] { tm }, null);
  87. }
  88. @Override
  89. public Socket createSocket(Socket socket, String host, int port,
  90. boolean autoClose) throws IOException, UnknownHostException {
  91. return sslContext.getSocketFactory().createSocket(socket, host,
  92. port, autoClose);
  93. }
  94. //核心程式碼
  95. @Override
  96. public void setHostnameVerifier(X509HostnameVerifier hostnameVerifier) {
  97. // TODO Auto-generated method stub
  98. ignoreVerifier = new X509HostnameVerifier() {
  99. @Override
  100. public void verify(String arg0, String[] arg1, String[] arg2)
  101. throws SSLException {
  102. }
  103. @Override
  104. public void verify(String arg0, X509Certificate arg1)
  105. throws SSLException {
  106. }
  107. @Override
  108. public void verify(String arg0, SSLSocket arg1)
  109. throws IOException {
  110. }
  111. //最最核心程式碼
  112. @Override
  113. public boolean verify(String arg0, SSLSession arg1) {
  114. return true;
  115. }
  116. };
  117. super.setHostnameVerifier(ignoreVerifier);
  118. }
  119. @Override
  120. public X509HostnameVerifier getHostnameVerifier() {
  121. return ignoreVerifier;
  122. }
  123. @Override
  124. public Socket createSocket() throws IOException {
  125. return sslContext.getSocketFactory().createSocket();
  126. }
  127. }
  128. }