本文从如下几个方面对https进行阐述:https的原理、认证方式、具体实践和对https请求的java调用。

1
2
HTTPS将HTTP协议与一组强大的对称、非对称和基于证书的加密技术结合在一起,
使得HTTPS不仅很安全,而且很灵活,很容易在处于无序状态、分散的全发球互联网上进行管理。

https原理

增加了SSL(Secure Sockets Layer 安全套接层),在进行TCP传输之前,先通过SSL层对数据进行加密,如下图所示。
https增加ssl层

认证方式

具体实践

一般部署方式:使用HTTPS/HTTP客户端网关,形式如下:
HTTPS/HTTP客户端网关

本地模拟https请求,使用Apache做网关,tomcat做应用服务器,配置工作分为如下几步:

  1. 使用openssl生成认证证书
  2. Apache配置https和转发

具体来说,openssl生成认证证书的步骤如下:

1
2
3
4
5
6
1. 下载并安装OpenSSL([下载地址](http://slproweb.com/products/Win32OpenSSL.html))
2. 使用如下命令生成证书
// 生成服务器端私钥文件:
openssl genrsa -des3 -out server.key 1024
//
3. 安装server.crt

Apache启用ssl,并作转发的步骤如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1. 配置转发
如下两行放开注释:
#LoadModule proxy_module modules/mod_proxy.so
#LoadModule proxy_http_module modules/mod_proxy_http.so
转发规则:
ProxyPass / http://127.0.0.1:8080
ProxyPassReverse / http://127.0.0.1:8080
2. 配置https
放开注释:
#LoadModule ssl_module modules/mod_ssl.so
#Include conf/extra/httpd-ssl.conf
修改httpd-ssl.conf文件,需在<VirtualHost _default_:443>标签中修改:
ServerName zt-httpstest:443
SSLCertificateFile "${SRVROOT}/conf/server.crt"
SSLCertificateKeyFile "${SRVROOT}/conf/server.key"

效果:
https效果

http请求https

客户端请求https时,可以让客户端信任所有服务器,也可以让客户端信任特定的服务器。 这里以客户端不验证服务器举例(读取特定服务器证书的方法见引用2)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import java.io.IOException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
* OKHttp测试
*/
public class OKHttpService {

private OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(createSSLSocketFactory(), new TrustAllCerts())
.hostnameVerifier(new TrustAllHostnameVerifier())
.build();

private static final MediaType JSON = MediaType.get("application/json; charset=utf-8");

/**
* get请求
*/
public String get(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
Response response = null;
try {
response = client.newCall(request).execute();
return response.body().string();
} finally {
if (response != null) {
response.close();
}
}
}

/**
* post请求
*/
public String post(String url, String json) throws IOException {
if (json == null) {
json = "";
}
RequestBody body = RequestBody.create(json.getBytes(), JSON);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = null;
try {
response = client.newCall(request).execute();
return response.body().string();
} finally {
if (response != null) {
response.close();
}
}
}


private static SSLSocketFactory createSSLSocketFactory() {
SSLSocketFactory ssf = null;
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, new TrustManager[] { new TrustAllCerts() }, new SecureRandom());
ssf = sc.getSocketFactory();
} catch (Exception e) {
}

return ssf;
}

/**
* 信任所有的服务器证书
*
*/
static class TrustAllCerts implements X509TrustManager {
public void checkClientTrusted(java.security.cert.X509Certificate[] var1, String var2)
throws CertificateException {
}

public void checkServerTrusted(java.security.cert.X509Certificate[] var1, String var2)
throws CertificateException {
}

public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}

/**
* 信任所有主机名
*
*/
static class TrustAllHostnameVerifier implements HostnameVerifier {
public boolean verify(String var1, SSLSession var2) {
return true;
}
}
}

引用

  1. 《HTTP权威指南》
  2. OKHttp对Https的认证的处理