由于项目需要配置一个ssl加密的通信,所以最近研究了一下tomcat下的ssl加密通信
步骤大约为三步
1.建立秘钥文件
利用jdk自带的功能导出秘钥文件
创建服务器密钥,
keytool -genkey -v -alias serverKey -dname "CN=data.robochina.com.cn" -keyalg RSA -keypass www.fulei.com.cn -keystore d:/workSoft/webssl/server.keystore -storepass www.fulei.com.cn
创建客户端秘钥:
keytool -genkey -v -alias clientKey -dname "CN=data.robochina.com.cn" -keyalg RSA -keypass www.fulei.com.cn -keystore d:/workSoft/webssl/clientKey.p12 -storepass www.fulei.com.cn -storetype PKCS12
将客户端密钥导出为证书文件
keytool -export -alias clientKey -file d:/workSoft/webssl/clientcer.cer -keystore d:/workSoft/webssl/clientKey.p12 -storepass www.fulei.com.cn -storetype PKCS12
将上述客户端密钥文件导入服务器证书库
keytool -import -v -alias clientKey -file d:/workSoft/webssl/clientcer.cer -keystore d:/workSoft/webssl/server.keystore -storepass www.fulei.com.cn
keytool 相关调用参数意义
2.设置tomcat
<Connector SSLEnabled="true" clientAuth="true"
maxThreads="150"
port="8443"
protocol="HTTP/1.1"
scheme="https"
secure="true"
sslProtocol="TLS"
keystoreFile="file:///d:/workSoft/webssl/server.keystore" keystorePass="www.fulei.com.cn"
truststoreFile="file:///d:/workSoft/webssl/server.keystore" truststorePass="www.fulei.com.cn"/>
3.项目配置强制https请求路径
<security-constraint>
<web-resource-collection>
<web-resource-name>must https</web-resource-name>
<url-pattern>/getWeiXinUserInfoLink</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
3.程序调用demo
package com.bjfulei.robo.machine.test;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManagerFactory;
/***
* Title:HttpsPost.java
* Description:
* Company: www.bjfulei.com.cn
* author: mingliang
* mail: 996036006@qq.com
* date: 2016年8月23日 下午3:10:53
*/
public class HttpsPost {
/**
* 获得KeyStore.
* @param keyStorePath
* 密钥库路径
* @param password
* 密码
* @return 密钥库
* @throws Exception
*/
public static KeyStore getKeyStore(String password, String keyStorePath)
throws Exception {
// 实例化密钥库
KeyStore ks = KeyStore.getInstance("JKS");
// 获得密钥库文件流
FileInputStream is = new FileInputStream(keyStorePath);
// 加载密钥库
ks.load(is, password.toCharArray());
// 关闭密钥库文件流
is.close();
return ks;
}
/**
* * 获得SSLSocketFactory. * @param password *
* 密码 * @param keyStorePath * 密钥库路径 * @param
* trustStorePath * 信任库路径 * @return
* SSLSocketFactory * @throws Exception
*/
public static SSLContext getSSLContext(String password,
String keyStorePath, String trustStorePath) throws Exception {
// 实例化密钥库
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
// 获得密钥库
KeyStore keyStore = getKeyStore(password, keyStorePath);
// 初始化密钥工厂
keyManagerFactory.init(keyStore, password.toCharArray());
// 实例化信任库
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
// 获得信任库
KeyStore trustStore = getKeyStore(password, trustStorePath);
// 初始化信任库
trustManagerFactory.init(trustStore);
// 实例化SSL上下文
SSLContext ctx = SSLContext.getInstance("TLS");
// 初始化SSL上下文
ctx.init(keyManagerFactory.getKeyManagers(),
trustManagerFactory.getTrustManagers(), null);
// 获得SSLSocketFactory
return ctx;
}
/**
* 初始化HttpsURLConnection.
* @param password
* 密码
* @param keyStorePath
* 密钥库路径
* @param trustStorePath
* 信任库路径
* @throws Exception
*/
public static void initHttpsURLConnection(String password,
String keyStorePath, String trustStorePath) throws Exception {
// 声明SSL上下文
SSLContext sslContext = null;
try {
sslContext = getSSLContext(password, keyStorePath, trustStorePath);
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
if (sslContext != null) {
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext
.getSocketFactory());
}
//验证证书域名不一致的以下请求host可以正常请求服务器获得返回
HttpsURLConnection.setDefaultHostnameVerifier( new HostnameVerifier(){
public boolean verify(String hostname, SSLSession paramSSLSession) {
if("localhost".equals(hostname)){
return true;
} else {
return false;
}
}
});
}
/**
* 发送请求.
* @param httpsUrl
* 请求的地址
* @param xmlStr
* 请求的数据
*/
public static void post(String httpsUrl, String xmlStr) {
HttpsURLConnection urlCon = null;
try {
urlCon = (HttpsURLConnection) (new URL(httpsUrl)).openConnection();
urlCon.setDoInput(true);
urlCon.setDoOutput(true);
urlCon.setRequestMethod("POST");
urlCon.setRequestProperty("Content-Length",
String.valueOf(xmlStr.getBytes().length));
urlCon.setUseCaches(false);
//设置为gbk可以解决服务器接收时读取的数据中文乱码问题
urlCon.getOutputStream().write(xmlStr.getBytes("utf-8"));
urlCon.getOutputStream().flush();
urlCon.getOutputStream().close();
BufferedReader in = new BufferedReader(new InputStreamReader(
urlCon.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
}
/**
* * 测试方法. * @param args * @throws Exception
*/
public static void main(String[] args) throws Exception {
// 密码
String password = "www.fulei.com.cn";
// 密钥库
String keyStorePath = "D:/workSoft/webssl/server.keystore";
// 信任库
String trustStorePath = "D:/workSoft/webssl/server.keystore";
// 本地起的https服务
//String httpsUrl = "https://data.robochina.com.cn:8443/machine/getWeiXinUserInfoLink?softVer=1.1&systemVer=1.2&machId=T001608090910";
String httpsUrl = "https://data.robochina.com.cn:8443/machine/getWeiXinUserInfoLink?softVer=1.1&systemVer=1.2&machId=T001608090910";
// 传输文本
HttpsPost.initHttpsURLConnection(password, keyStorePath, trustStorePath);
// 发起请求
HttpsPost.post(httpsUrl, "");
}
}