前言
本节我们将学习一下关于HttpClient请求在遇到SSL证书认证时如何绕过认证环节。如今在整个Internet中主流的Protocol HTTPS 以它自身的有时几乎替代了HTTP,基于HTTPS自由的特性,它需要证书认证来保证请求URL和数据的安全可靠,因而本节将重点学习一下如何在使用HTTPS请求数据是绕开SSL认证证书。在整个实现的过程中我们将选择性讲解一下代码试下你的逻辑。
HttpClientUtils.java
import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.OutputStreamWriter; import java.net.URL; import java.net.URLConnection; import org.apache.commons.io.IOUtils; /** * 封装新的HttpClient 请求,绕过签证 * @author baixiaodong * */ public class HttpClientUtils { /** * 忽略HTTPS请求的SSL证书,必须在openConnection之前调用 * * @throws Exception */ private static void trustAllHttpsCertificates() throws Exception { TrustManager[] trustAllCerts = new TrustManager[1]; TrustManager tm = new miTM(); trustAllCerts[0] = tm; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, null); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } static class miTM implements TrustManager, X509TrustManager { public X509Certificate[] getAcceptedIssuers() { return null; } public boolean isServerTrusted(X509Certificate[] certs) { return true; } public boolean isClientTrusted(X509Certificate[] certs) { return true; } public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException { return; } public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException { return; } } /** * 忽略HTTPS请求的SSL证书,必须在openConnection之前调用 * * @throws Exception */ public static void ignoreSsl() throws Exception { HostnameVerifier hv = new HostnameVerifier() { public boolean verify(String urlHostName, SSLSession session) { System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost()); return true; } }; trustAllHttpsCertificates(); HttpsURLConnection.setDefaultHostnameVerifier(hv); } /** * 忽略SSL证书的Get请求 * @param url * @param timeOut 默认 3000 * @return * @throws Exception */ public static String getRequest(String url, int timeOut) throws Exception { URL u = new URL(url); if ("https".equalsIgnoreCase(u.getProtocol())) { ignoreSsl(); } URLConnection conn = u.openConnection(); conn.setConnectTimeout(timeOut); conn.setReadTimeout(timeOut); return IOUtils.toString(conn.getInputStream()); } /** * 忽略SSL证书的POST请求 * @param urlAddress * @param args * @param timeOut * @return * @throws Exception */ public static String postRequest(String urlAddress, String args, int timeOut) throws Exception { URL url = new URL(urlAddress); if ("https".equalsIgnoreCase(url.getProtocol())) { ignoreSsl(); } URLConnection u = url.openConnection(); u.setDoInput(true); u.setDoOutput(true); u.setConnectTimeout(timeOut); u.setReadTimeout(timeOut); OutputStreamWriter osw = new OutputStreamWriter(u.getOutputStream(), "UTF-8"); osw.write(args); osw.flush(); osw.close(); u.getOutputStream(); return IOUtils.toString(u.getInputStream()); } }
小结
使用如上方法便可以绕过证书认证部分,当实际上我是不推荐这样做的,因为这种获取数据的行为属于Cheat行为,理论上是违背互联网安全协议的,其次我们没有通过SSL证书认证授权,无法确保URL和数据的正确性和可用性。