赞
踩
http是一种普通的传输协议,在互联网上,所有的文件都要遵守这个HTTP协议,同时超文本也是http传输的基本部分,实现客户端和服务器的相互请求。
https是http的安全版本 就是http+ssl,也叫超文本安全传输,https是有加密传输协议的通道,并且SSL提供了安全加密基础 SSL需要证书,https主要是用于http的传输,并且在HTTP与TCP之间有一个特殊的加密/身份验证。
//此处使用DefaultHttpClient为了在之后体现与HttpClient调用HTTPS的区别
DefaultHttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("https://autumnfish.cn/api/joke/list?num=2");
try {
HttpResponse res = client.execute(post);
String result = EntityUtils.toString(res.getEntity());
System.out.println("result==>"+result);
} catch (IOException e) {
e.printStackTrace();
}
为了避免需要证书,所以用一个类继承DefaultHttpClient类,忽略校验过程
代码
import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.impl.client.DefaultHttpClient; public class SSLClient extends DefaultHttpClient { public SSLClient() throws Exception{ super(); //SSL:Secure Sockets Layer,一种加密协议规范,如https就使用它进行加解密 //TLS:安全传输层协议(TLS)用于在两个通信应用程序之间提供保密性和数据完整性。该协议由两层组成: TLS 记录协议(TLS Record)和 TLS 握手协议(TLS Handshake)。 //创建SSL的上下文类 SSLContext ctx = SSLContext.getInstance("TLS"); //实现自己的x509TrustManager类,并复写三种方法 X509TrustManager tm = new X509TrustManager() { //给出同位体提供的部分或完整的证书链,构建到可信任的根的证书路径,并且返回是否可以确认和信任将其用于基于验证类型的客户端 ssl 验证。 //原本这三个方法中验证SSL,复写置其内容为空 @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return null; } }; //初始化SSLContext 传入数组 ctx.init(null, new TrustManager[]{tm}, null); //工厂创建SSL套接字 //ALLOW_ALL_HOSTNAME_VERIFIER 允许所有主机名验证器 SSLSocketFactory ssf = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); //主要作用是用于创建http连接的工厂使用,管理[长连接](https://baike.baidu.com/item/%E9%95%BF%E8%BF%9E%E6%8E%A5/568486?fr=kg_general),同步化访问长连接,保证同一时间只有一个线程访问连接。不再推荐使用 ClientConnectionManager ccm = this.getConnectionManager(); //scheme 策略 //策略注册 SchemeRegistry sr = ccm.getSchemeRegistry(); //方法参数列表:String name(策略名), int port(端口号), SchemeSocketFactory factory(策略套接字工厂) sr.register(new Scheme("https", 443, ssf)); } }
代码
httpClient = new SSLClient();
此处上篇文章有相关方法以及参数的含义描述讲解,此处略
import com.example.httpstest.client.SSLClient; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.message.BasicHeader; import org.apache.http.util.EntityUtils; public class HttpClientUtil { public static String doGet(String url,String charset) throws Exception{ HttpClient httpClient = null; HttpGet httpGet = null; String result = null; httpClient = new SSLClient(); httpGet = new HttpGet(url); httpGet.addHeader("Content-Type", "application/json"); //httpGet.setEntity(se); HttpResponse response = httpClient.execute(httpGet); if(response != null){ HttpEntity resEntity = response.getEntity(); if(resEntity != null){ result = EntityUtils.toString(resEntity,charset); } } return result; } public static String doPost(String url,String json,String charset) throws Exception{ HttpClient httpClient = null; HttpPost httpPost = null; String result = null; httpClient = new SSLClient(); httpPost = new HttpPost(url); httpPost.addHeader("Content-Type", "application/json"); StringEntity se = new StringEntity(json); se.setContentType("text/json"); se.setContentEncoding(new BasicHeader("Content-Type", "application/json")); httpPost.setEntity(se); HttpResponse response = httpClient.execute(httpPost); if(response != null){ HttpEntity resEntity = response.getEntity(); if(resEntity != null){ result = EntityUtils.toString(resEntity,charset); } } return result; } }
代码
//post调用HTTPS
String url = "https://autumnfish.cn/api/user/reg";
String json = "{\n" +
" \"username\":\"Mike\"\n" +
"}";
String str = null;
try {
str = HttpClientUtil.doPost(url, json, "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("post调用HTTPS==>"+str);
代码
//get调用HTTPS
String url2 = "https://autumnfish.cn/api/joke/list?num=2";
String str2 = null;
try {
str2 = HttpClientUtil.doGet(url2, "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("get调用HTTPS==>"+str2);
HttpClient client = new DefaultHttpClient();
//变为:
HttpClient client = HttpClientBuilder.create().build();
//CloseableHttpClient是HttpClient子类
//即:
CloseableHttpClient client = HttpClients.createDefault();
前者不再更新维护,后者提供更好的性能以及更大的灵活性
原理如下:
根源在于在连接管理器中注册了不同的连接创建工厂。当访问url的schema为http时,调用明文连接套接字工厂来建立连接;当访问url的schema为https时,调用SSL连接套接字工厂来建立连接。
让我们的HttpClient具有多线程处理的能力,连接管理器选用了PoolingHttpClientConnectionManager,将协议注册信息传入连接管理器,最后再次利用构造器的模式创建出我们需要的HttpClient。随后的GET/POST请求发起方法http和https之间没有差异。
代码如下:
private CloseableHttpClient createClient(HttpUriRequest request) { HttpClientBuilder httpBuilder = HttpClients.custom(); //不进行重定向 if (this.redirect) { httpBuilder.disableRedirectHandling(); } //URI是https的请求 if (request.getURI().getScheme().equals("https")) { //创建重写的SSL上下文去绕过验证 SSLContext sslcontext = createIgnoreVerifySSL(); //设置协议http和https对应的处理socket链接工厂的对象 //明文套接字与SSL套接字 Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() .register("http", PlainConnectionSocketFactory.INSTANCE) .register("https", new SSLConnectionSocketFactory(sslcontext)) .build(); //创建ConnectionManager,添加Connection配置信息 PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); httpBuilder.setConnectionManager(connManager); } //返回创建的CloseableHttpClient return httpBuilder.build(); }
//创建SSL的上下文类方法,返回类型是SSLContext public static SSLContext createIgnoreVerifySSL() { SSLContext sc = null; try { //SSLv3.0 与 TLS 相比几乎没有做什么改动 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; } }; //初始化SSLContext 传入TrustManager数组 sc.init(null, new TrustManager[]{trustManager}, null); } catch (NoSuchAlgorithmException | KeyManagementException e) { e.printStackTrace(); throw new RuntimeException(e); } //返回 return sc; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。