本人在作接口自動化的過程當中,遇到了請求第三方https協議請求,在通過了短暫的知識從新學習以後,寫完代碼執行起來老是遇到一個異常,在用客戶端執行請求的時候拋出來的,下面是異常的信息:html
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.Alerts.getSSLException(Alerts.java:154) at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353) at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134) at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353) at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380) at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184) at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88) at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
查閱了不少資料,大部分都說是由於java自己安全機制引發的,從新去官網下載jar包替換便可。如下是修改方法:java
由於jdk中jce的安全機制致使報的錯,要去oracle官網下載對應的jce包替換jdk中的jce包。 jce所在地址: %JAVA_HOME%\jre\lib\security裏的local_policy.jar,US_export_policy.jarpython
具體異常教程以下:傳送門編程
在緣由的第二種裏面,有一個須要校驗自己的TLS的版本和服務端版本是否一致,我就是在這裏出了問題,致使的這個異常。由於我一直用的默認參數去建立新的套接字對象。下面是我用Charles攔截的請求的header信息:安全
上面圈起來的地方就是現實的服務器的TLS版本,相應地改掉本身代碼的中設置版本的地方便可。服務器
下面是個人代碼:大多數參考了網上的教程,本身作了一些修改,大同小異。下面是獲取SSLcontext對象的方法,實現了X509TrustManager接口,裏面方法不用修改。oracle
/** * 獲取SSL套接字對象 重點重點:設置tls協議的版本 * * @return */ public static SSLContext createIgnoreVerifySSL() { SSLContext sslContext = null;// 建立套接字對象 try { sslContext = SSLContext.getInstance("TLSv1.2");//指定TLS版本 } catch (NoSuchAlgorithmException e) { SourceCode.getInstance().output("建立套接字失敗!", e); } // 實現X509TrustManager接口,用於繞過驗證 X509TrustManager trustManager = new X509TrustManager() { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException { } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } }; try { sslContext.init(null, new TrustManager[] { trustManager }, null);//初始化sslContext對象 } catch (KeyManagementException e) { SourceCode.getInstance().output("初始化套接字失敗!", e); } return sslContext; }
下面是建立https協議的client的方法,其中用到了鏈接池的使用:框架
/** * 獲取https協議請求對象 * * @return */ public static CloseableHttpClient getCloseableHttpsClients() { // 採用繞過驗證的方式處理https請求 SSLContext sslcontext = createIgnoreVerifySSL(); // 設置協議http和https對應的處理socket連接工廠的對象 Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create() .register("http", PlainConnectionSocketFactory.INSTANCE) .register("https", new SSLConnectionSocketFactory(sslcontext)).build(); PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); HttpClients.custom().setConnectionManager(connManager); // 建立自定義的httpsclient對象 CloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).build(); return client; }
還有一個繼承httpclient類,重寫createDefault()方法來實現請求https的,通過實驗,對於一些https協議是沒有問題的。socket