调用HTTPS与HTTP接口
1 http与https
2 https和http的区别
- 1、https的端口是443,而http的端口是80,且两者的连接方式不同;
- 2、http传输是明文的,而https是用ssl进行加密的,https的安全性更高;
- 3、https是需要申请证书的,而http不需要。
3 HttpClient方式调用https接口实现
3.1 正常使用HttpClient调用http接口
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();
}
3.1.1正常调HTTP方式调用HTTPS接口结果
3.2 httpClient调用https接口实现具体步骤
3.2.1 创建SSLClient类继承DefaultHttpClient(重新DefaultHttpClient)
为了避免需要证书,所以用一个类继承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();
SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
@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;
}
};
ctx.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager ccm = this.getConnectionManager();
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", 443, ssf));
}
}
3.2.2 HttpClientUtil中使用该新建的DefaultHttpClient 复写类
代码
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");
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;
}
}
3.3 Demo测试调用
3.3.1 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);
3.3.1.1 调用结果
3.3.2 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);
3.3.2.1 调用结果
4 总结
4.1 DefaultHttpClient与HttpClient的区别
4.1.1 代码变化
HttpClient client = new DefaultHttpClient();
HttpClient client = HttpClientBuilder.create().build();
CloseableHttpClient client = HttpClients.createDefault();
4.1.2 变化原因(过时原因)
前者不再更新维护,后者提供更好的性能以及更大的灵活性
4.2 HttpClient调用https接口原理
4.2.1 以下是上述的进一步完善(可以根据url中是否https进行连接建立)
原理如下:
根源在于在连接管理器中注册了不同的连接创建工厂。当访问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();
}
if (request.getURI().getScheme().equals("https")) {
SSLContext sslcontext = createIgnoreVerifySSL();
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", new SSLConnectionSocketFactory(sslcontext))
.build();
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
httpBuilder.setConnectionManager(connManager);
}
return httpBuilder.build();
}
public static SSLContext createIgnoreVerifySSL() {
SSLContext sc = null;
try {
sc = SSLContext.getInstance("SSLv3");
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);
} catch (NoSuchAlgorithmException | KeyManagementException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
return sc;
}
|