https单向认证和双向认证
一;单向认证
浏览器访问https单向认证:
1.服务器端提供服务器证书,验证服务器身份。
2.由CA机构签发的数字证书无需在客户端(浏览器)“受信任证书中”导入,自签名证书zlex.cer(服务器证书)需手动进行导入(证书验证)
3.使用tomcat作为服务器,须在tomcat的server.xml文件中配置SSL/TLS协议
4.将签发的数字证书zlex.cer导入到密钥库zlex.keystore中。将zlex.keystore放在tomcat的conf目录下,并在serverlet.xml中配置SSL/TLS的单向认证。
5.此时就可以通过浏览器访问tomcat。若访问失败,还需在客户端(浏览器)中导入根证书,之后就可以成功访问tomcat主页,也可以编写jsp页面,通过tomcat发布,获取https的相关信息,如数字证书的加密算法、密钥长度
java代码访问https单向认证:
1.只需获得服务器端的数字证书,并将其导入密钥库应用相应的java API 即可进行加密交互。
例子:
package com.httpsDemo; import java.io.FileInputStream; import java.security.KeyStore; import java.security.SecureRandom; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; // https单向访问服务 public abstract class HTTPSCoder { // 1.协议:支持TLS和SSL协议 public static final String PROTOCOL = "TLS"; // 2.获得密钥库 private static KeyStore getKeyStore(String keyStorePath, String password) throws Exception { // 实例化密钥库 KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); // 获得密钥库文件流 FileInputStream is = new FileInputStream(keyStorePath); // 加载密钥库 ks.load(is, password.toCharArray()); // 关闭密钥库文件流 is.close(); return ks; } // 3.获得SSLSocketFactory private static SSLSocketFactory getSSLSocketFactory(String password, String keyStorepath, String trustStorePath) throws Exception { // 实例化密钥库工厂 KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); // 获得密钥库 KeyStore keyStore = getKeyStore(keyStorepath, password); // 初始化密钥库工厂 keyManagerFactory.init(keyStore, password.toCharArray()); // 实例化信任库工厂 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); // 获得信任库 KeyStore trustStore = getKeyStore(trustStorePath, password); // 初始化信任库 trustManagerFactory.init(trustStore); // 实例化SSL上下文 SSLContext ctx = SSLContext.getInstance(PROTOCOL); // 初始化SSL上下文 ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom()); // 获得SSLSocketFactory return ctx.getSocketFactory(); } // 4.为HttpsURLConnection配置SSLSocketFactory public static void configSSLSocketFactory (HttpsURLConnection conn, String password, String keyStorePath, String trustStorePath ) throws Exception { // 获得SSLSocketFactory SSLSocketFactory sslSocketFactory = getSSLSocketFactory(password, keyStorePath, trustStorePath); // 设置SSLSocketFactory conn.setSSLSocketFactory(sslSocketFactory); } }
测试:
package com.httpsDemo; import java.io.DataInputStream; import java.net.URL; import javax.net.ssl.HttpsURLConnection; // https测试:内容传输时已经对加密解密进行了封装操作,我们不必去关心 public class HTTPSCoderTest { // 密钥库/信任库密码 private static String password = "123456"; // 密钥库文件路径 private static String keyStorePath = "D:/zlex.keystore"; // 信任库文件路径 private static String trustStorePath = "D:/zlex.keystore"; // 访问地址 private static String httpsUrl = "https://www.zlex.org/ssl/"; // https验证 public static void main(String[] args) throws Exception { // TODO Auto-generated method stub // 建立HTTPS连接 URL url = new URL(httpsUrl); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); // 打开输入输出流 conn.setDoInput(true); // 为HttpsURLConnection配置SSLSocketFactory HTTPSCoder.configSSLSocketFactory(conn, password, keyStorePath, trustStorePath); // 鉴别内容长度(长度不等于-1说明连接成功) int length = conn.getContentLength(); byte[] data = null; // 如果内容长度为-1,则放弃解析 if (length != -1) { DataInputStream dis = new DataInputStream(conn.getInputStream()); data = new byte[length]; dis.readFully(data); dis.close(); System.err.println(new String(data)); } // 关闭连接 conn.disconnect(); // 验证内容 //assertNotNull(data); } }
二:https双向认证
1.使用的证书:ca.p12(根证书)、server.p12(服务端证书)、client.p12(客户端证书)
2.将ca.p12证书、client.p12证书导入浏览器(和zlex.cer导入一样)
3.进行服务器配置:将ca.p12和server.p12复制到tomcat的conf目录下,同时通过在浏览器中导入ca.p12和client.p12文件
4.在tomcat的server.xml中配置双向认证:scheme="https" clientAute="true"(打开双向验证)。双向认证服务端区分信任库和密钥库。此时将server.p12作为密钥库文件,ca.p12作为信任库文件
双向认证代码:
package com.httpsDemo; import java.io.FileInputStream; import java.security.KeyStore; import java.security.SecureRandom; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; // https单向访问服务 public abstract class HTTPSCoder { // 1.协议:支持TLS和SSL协议 public static final String PROTOCOL = "TLS"; // 2.获得密钥库 private static KeyStore getKeyStore(String keyStorePath, String password) throws Exception { // 实例化密钥库:使用PKCS#12格式的个人信息交换文件作为密钥库和信任库文件 KeyStore ks = KeyStore.getInstance("PKCS12"); // 获得密钥库文件流 FileInputStream is = new FileInputStream(keyStorePath); // 加载密钥库 ks.load(is, password.toCharArray()); // 关闭密钥库文件流 is.close(); return ks; } // 3.获得SSLSocketFactory private static SSLSocketFactory getSSLSocketFactory(String password, String keyStorepath, String trustStorePath) throws Exception { // 实例化密钥库工厂 KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); // 获得密钥库 KeyStore keyStore = getKeyStore(keyStorepath, password); // 初始化密钥库工厂 keyManagerFactory.init(keyStore, password.toCharArray()); // 实例化信任库工厂 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); // 获得信任库 KeyStore trustStore = getKeyStore(trustStorePath, password); // 初始化信任库 trustManagerFactory.init(trustStore); // 实例化SSL上下文 SSLContext ctx = SSLContext.getInstance(PROTOCOL); // 初始化SSL上下文 ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom()); // 获得SSLSocketFactory return ctx.getSocketFactory(); } // 4.为HttpsURLConnection配置SSLSocketFactory public static void configSSLSocketFactory (HttpsURLConnection conn, String password, String keyStorePath, String trustStorePath ) throws Exception { // 获得SSLSocketFactory SSLSocketFactory sslSocketFactory = getSSLSocketFactory(password, keyStorePath, trustStorePath); // 设置SSLSocketFactory conn.setSSLSocketFactory(sslSocketFactory); } }
测试:
package com.httpsDemo; import java.io.DataInputStream; import java.net.URL; import javax.net.ssl.HttpsURLConnection; // https测试:内容传输时已经对加密解密进行了封装操作,我们不必去关心 public class HTTPSCoderTest { // 密钥库/信任库密码 private static String password = "123456"; // 密钥库文件路径 private static String keyStorePath = "D:/server.p12"; // 信任库文件路径 private static String trustStorePath = "D:/ca.p12"; // 访问地址 private static String httpsUrl = "https://www.zlex.org/ssl/"; // https验证 public static void main(String[] args) throws Exception { // TODO Auto-generated method stub // 建立HTTPS连接 URL url = new URL(httpsUrl); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); // 打开输入输出流 conn.setDoInput(true); // 为HttpsURLConnection配置SSLSocketFactory HTTPSCoder.configSSLSocketFactory(conn, password, keyStorePath, trustStorePath); // 鉴别内容长度(长度不等于-1说明连接成功) int length = conn.getContentLength(); byte[] data = null; // 如果内容长度为-1,则放弃解析 if (length != -1) { DataInputStream dis = new DataInputStream(conn.getInputStream()); data = new byte[length]; dis.readFully(data); dis.close(); System.err.println(new String(data)); } // 关闭连接 conn.disconnect(); // 验证内容 //assertNotNull(data); } }