HttpClient:绕开https证书(三)
HTTP 協議可能是現在 Internet 上使用得最多、最重要的協議了,越來越多的 Java 應用程序需要直接通過 HTTP 協議來訪問網絡資源。雖然在 JDK 的 java.net 包中已經提供了訪問 HTTP 協議的基本功能,但是對于大部分應用程序來說,JDK 庫本身提供的功能還不夠豐富和靈活。HttpClient 是 Apache Jakarta Common 下的子項目,用來提供高效的、最新的、功能豐富的支持 HTTP 協議的客戶端編程工具包,并且它支持 HTTP 協議最新的版本和建議。HttpClient 已經應用在很多的項目中,比如 Apache Jakarta 上很著名的另外兩個開源項目 Cactus 和 HTMLUnit 都使用了 HttpClient。
當前官網最新版介紹頁是:Apache HttpComponents – HttpClient Overview
使用HttpClient發送請求、接收響應很簡單,一般需要如下幾步即可:
使用https就需要重新構建sslContext對象,把證書塞進去(因為可以改變策略的地方叫較多,很多人一開始被搞得暈頭轉向,不如全圍繞sslContext來構建)
// 構建一個新的證書管理器,重寫本該校驗的方法,空的就行 public class AlltrustManager implements X509TrustManager {@Overridepublic void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {}@Overridepublic void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {}@Overridepublic X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];} }寫一個https的工具類:
import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpPost; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import sun.misc.JavaSecurityAccess;import javax.net.ssl.SSLContext; import javax.net.ssl.X509TrustManager; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Map; import java.util.logging.Logger;public class HttpUtils {private static Logger logger = Logger.getLogger("HttpUtils.class");public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {//關鍵就是這個sslcontextSSLContext context = SSLContext.getInstance("SSLv3");X509TrustManager[] alltrustManager = new X509TrustManager[0];context.init(null,alltrustManager, new SecureRandom() );return context;}public static String doPostRequest(String url, Map<String,String> headers,String requestBody) throws NoSuchAlgorithmException, KeyManagementException {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);connManager.setMaxTotal(200);//最大連接數connManager.setDefaultMaxPerRoute(100);//單個服務并發數HttpClients.custom().setConnectionManager(connManager);//創建自定義的httpclient對象CloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).build();//創建post方式請求對象HttpPost httpPost = new HttpPost(url);//添加headerif (headers!=null){for (Map.Entry<String, String> entry : headers.entrySet()) {httpPost.setHeader(entry.getKey(), entry.getValue());}}//添加bodyByteArrayEntity entity = null;try {entity = new ByteArrayEntity(requestBody.getBytes("UTF-8"));entity.setContentType("application/json");} catch (UnsupportedEncodingException e) {logger.info("向服務器承保接口發起http請求,封裝請求body時出現異常"+e);throw new RuntimeException("向服務器承保接口發起http請求,封裝請求body時出現異常", e);}httpPost.setEntity(entity);//執行post請求HttpResponse response = null;try {response = client.execute(httpPost);} catch (IOException e) {logger.info("提交給服務器的請求,不符合HTTP協議"+ e);throw new RuntimeException("提交給服務器的請求,不符合HTTP協議", e);}logger.info("狀態碼:" + response.getStatusLine());return response.toString();}}如果不想重寫接口,也可以單獨構造:
/** * 繞過驗證 * * @return * @throws NoSuchAlgorithmException * @throws KeyManagementException */ public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException { SSLContext sc = SSLContext.getInstance("SSLv3"); // 實現一個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; } }; sc.init(null, new TrustManager[] { trustManager }, null); return sc; }然后來驗證一下:
public final static void main(String[] args) throws Exception {String body = "";//采用繞過驗證的方式處理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); //創建自定義的httpclient對象 CloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).build(); //CloseableHttpClient client = HttpClients.createDefault();try{//創建post方式請求對象 HttpPost httpPost = new HttpPost("https://api.douban.com/v2/book/1220562"); //指定報文頭Content-type、User-AgenthttpPost.setHeader("Content-type", "application/x-www-form-urlencoded"); httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:6.0.2) Gecko/20100101 Firefox/6.0.2");//執行請求操作,并拿到結果(同步阻塞) CloseableHttpResponse response = client.execute(httpPost); //獲取結果實體 HttpEntity entity = response.getEntity(); if (entity != null) { //按指定編碼轉換結果實體為String類型 body = EntityUtils.toString(entity, "UTF-8"); } EntityUtils.consume(entity); //釋放鏈接 response.close(); System.out.println("body:" + body);}finally{client.close();}}如果要使用自己的證書呢?
sslcontext = SSLContexts.custom().loadTrustMaterial(new File("D://https//ca//cl.jks"),"123456".toCharArray(),new TrustSelfSignedStrategy()).build();具體可參考此文:http://www.javashuo.com/article/p-ooekqaim-e.html參考:
使用HttpClient鏈接池進行https單雙向驗證 - JavaShuo
使用HttpClient發起請求時將參數放入requestBody中_weixin_33721344的博客-CSDN博客
輕松把玩HttpClient之配置ssl,采用繞過證書驗證實現https_崔成龍 . 勇往直前-CSDN博客
HttpClient配置SSL繞過https證書_irokay的專欄-CSDN博客
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的HttpClient:绕开https证书(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (二):集成日志框架:springboo
- 下一篇: Idea使用技巧总结(未完待续)