调用第三方接口时发现这么一个现象,都说在某月某日停止对HTTP请求的维护,改为HTTPS方式的请求。我觉得我需要未雨绸缪一下,免得到时候自己忘记了给自己挖坑。这边记录一下我自己的HTTPS请求工具类。
有必要了解下HTTP和HTTPS两种不同请求的区别。
HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。
HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。
HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。
HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。
HTTPS和HTTP的区别主要如下:
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
public class SSLClient extends DefaultHttpClient{
public SSLClient() throws Exception{
super();
//传输协议需要根据自己的判断
SSLContext ctx = SSLContext.getInstance("TLSv1.2");
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));
}
}
其实和我之前接口调用中的相关博客改动较大的就是这个地方,因为我们的HTTPS请求方式是基于SSL证书的,所以普通的HTTP请求是不符合我们的需求的,图中的'TLSv1.2'所匹配的是jdk1.8版本,大家要根据自己的jdk版本自己匹配。
我不知道我的图为什么传不上来..... 实际上jdk1.6,1.7,1.8三个版本都可以传入'TLSv1.1'
实现这个https方法的信任管理器后,我们需要封装一下自己的get和post请求,我们先来看get请求
public static String doGet(String url, Map map, String charset){
HttpClient httpClient = null;
HttpGet httpGet = null;
String result = null;
String urls = jointParamsToUrl(map,url);
try{
httpClient = new SSLClient();
httpGet = new HttpGet(urls);
HttpResponse response = httpClient.execute(httpGet);
if(response != null){
HttpEntity resEntity = response.getEntity();
if(resEntity != null){
result = EntityUtils.toString(resEntity,charset);
}
}
}catch(Exception ex){
ex.printStackTrace();
}
return result;
}
public static String jointParamsToUrl(Map params,String url){
if(params==null){
return url;
}
StringBuffer temp = new StringBuffer();
String param = "";
for (String key : params.keySet()) {
Object value = params.get(key);
if(value!=null){
String s = value.toString();
if(StringUtils.isNotEmpty(s)){
temp.append(key).append("=").append(s).append("&");
}
}
}
if(temp.length()>0){
param = temp.substring(0,temp.length()-1);
}
if(url.charAt(url.length()-1)=='?'){
url = url+"&"+param;
}else {
url = url+"?"+param;
}
return url;
}
这个是get请求,将url和请求参数进行拼接,然后进行请求,记住一点,需要new出一个SSLClient(), httpClient = new SSLClient();这样就可以拿到相应的信任管理器。
public static String doPost(String url, Map map, String charset){
HttpClient httpClient = null;
HttpPost httpPost = null;
String result = null;
try{
httpClient = new SSLClient();
httpPost = new HttpPost(url);
//设置参数
List list = new ArrayList();
Iterator iterator = map.entrySet().iterator();
while(iterator.hasNext()){
Map.Entry elem = (Map.Entry) iterator.next();
list.add(new BasicNameValuePair(elem.getKey(),elem.getValue()));
}
if(list.size() > 0){
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list,charset);
httpPost.setEntity(entity);
}
HttpResponse response = httpClient.execute(httpPost);
if(response != null){
HttpEntity resEntity = response.getEntity();
if(resEntity != null){
result = EntityUtils.toString(resEntity,charset);
}
}
}catch(Exception ex){
ex.printStackTrace();
}
return result;
}
再就是post请求了,后期如果说有请求头的设计等需求,可以对比着我之前接口系列文档的相关文章进行编写。
public static void main(String[] args) {
String charset = "utf-8";
String url="https://apis.map.qq.com/ws/coord/v1/translate";
Map createMap = new HashMap();
createMap.put("locations","39.12,116.83;30.21,115.43");
createMap.put("type","3");
createMap.put("key","");
String message=doGet(url,createMap,charset);
System.out.println(message);
}
最后一个测试类进行测试,现在仅仅只是粗略看一下,等到后期用到再详细研究下。