本文从如下几个方面对https进行阐述:https的原理、认证方式、具体实践和对https请求的java调用。
1 2
| HTTPS将HTTP协议与一组强大的对称、非对称和基于证书的加密技术结合在一起, 使得HTTPS不仅很安全,而且很灵活,很容易在处于无序状态、分散的全发球互联网上进行管理。
|
https原理
增加了SSL(Secure Sockets Layer 安全套接层),在进行TCP传输之前,先通过SSL层对数据进行加密,如下图所示。
认证方式
具体实践
一般部署方式:使用HTTPS/HTTP客户端网关,形式如下:
本地模拟https请求,使用Apache做网关,tomcat做应用服务器,配置工作分为如下几步:
- 使用openssl生成认证证书
- 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"
|
效果:
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; } } }
|
引用
- 《HTTP权威指南》
- OKHttp对Https的认证的处理