java + https + tomcat 双向认证(含证书生成和代码实现)

 JAVA 代码

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

import net.sf.json.JSONObject;


/**
 * <p>
 * Description
 * </p>
 * 
 * @author Admin
 * @date 2019年4月23日
 */
public class HttpsPost {

	/**
	 * 加载私钥证书
	 * 
	 * @param keyStore
	 * @param keyStorePass
	 * @return
	 * @throws IOException
	 */
	private static KeyManager[] getKeyManagers(String keyStore,
			String keyStorePass) throws Exception {
		try {
			// 获取默认的 X509算法 
			String alg = KeyManagerFactory.getDefaultAlgorithm();
			// 创建密钥管理工厂  
			KeyManagerFactory factory = KeyManagerFactory.getInstance(alg);
			InputStream fp = new FileInputStream(keyStore);
			KeyStore ks = KeyStore.getInstance("JKS");//PKCS12
			ks.load(fp, keyStorePass.toCharArray());
			fp.close();
			factory.init(ks, keyStorePass.toCharArray());
			KeyManager[] keyms = factory.getKeyManagers();
			//System.out.println(keyms);
			return keyms;
		}catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 加载信任证书库
	 * 
	 * @param trustStore
	 * @param trustStorePass
	 * @return
	 * @throws IOException
	 */
	private static TrustManager[] getTrustManagers(String trustStore,
			String trustStorePass) throws Exception {
		try {
			// 信任仓库的默认算法X509 
			String alg = TrustManagerFactory.getDefaultAlgorithm();
			// 获取信任仓库工厂  
			TrustManagerFactory factory = TrustManagerFactory.getInstance(alg);
			// 读取信任仓库 
			InputStream fp = new FileInputStream(trustStore);
			// 密钥类型
			KeyStore ks = KeyStore.getInstance("JKS");
			// 加载密钥 
			ks.load(fp, trustStorePass.toCharArray());
			fp.close();
			factory.init(ks);
			TrustManager[] tms = factory.getTrustManagers();
			//System.out.println(tms);
			return tms;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	//  直接通过主机认证
	private final static HostnameVerifier VERIFY = new HostnameVerifier() {
		@Override
		public boolean verify(String hostname, SSLSession session) {
			return true;
		}
	};

	public static String https(String url, Map<String, String> params){
		// 构建请求参数
		String result = "";
		PrintWriter out = null;
		BufferedReader in = null;
		HttpsURLConnection urlCon = null;

		JSONObject json = JSONObject.fromObject(params);
		String sendString = json.toString();
		System.out.println("=====https发送的数据为:\t" + sendString);
		try {
			// 授信证书库
			String trustStore = "D:\\workSoft\\cer\\trustOfClient.keystore";
			String trustStorePass = "123456";
			// 私钥证书
			String keyStore = "D:\\workSoft\\cer\\client.keystore";
			String keyStorePass = "123456";
			TrustManager[] tms = getTrustManagers(trustStore, trustStorePass);
			KeyManager[] kms = getKeyManagers(keyStore, keyStorePass);
			SSLContext sslContext = SSLContext.getInstance("SSL");//"SunJSSE"
			//SSLContext sslContext = SSLContext.getInstance("TLS");//TLS   SSL
			// 如果服务器不要求私钥证书,kms 可以不填
			sslContext.init(kms, tms,null );//new java.security.SecureRandom()
			SSLSocketFactory ssf = sslContext.getSocketFactory();

			URL url2 = new URL(url);
			urlCon = (HttpsURLConnection) url2.openConnection();
			urlCon.setSSLSocketFactory(ssf);
			urlCon.setHostnameVerifier(VERIFY);
			urlCon.setDoOutput(true);
			urlCon.setDoInput(true);
			urlCon.setRequestMethod("POST");
			urlCon.setRequestProperty("Content-type", "application/json;charset=UTF-8");
			urlCon.setRequestProperty("accept", "*/*"); //请求报文可通过一个“Accept”报文头属性告诉服务端 客户端接受什么类型的响应
			urlCon.setRequestProperty("connection", "Keep-Alive");//表示是否需要持久连接。(HTTP 1.1默认进行持久连接)Keep-Alive为持久连接
			//urlCon.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 7.0; WOW64)");
			urlCon.setConnectTimeout(3*1000);//设置超时时间
			urlCon.setReadTimeout(3*1000);
			// 发送POST请求必须设置如下两行
			urlCon.setDoOutput(true);
			urlCon.setDoInput(true);
			// 获取URLConnection对象对应的输出流
			OutputStream os = urlCon.getOutputStream(); 

			//参数是键值队  , 不以"?"开始 
			os.write(sendString.getBytes()); 
			os.flush();
			// 发送请求参数
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(urlCon.getInputStream(),"GBK"));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			e.printStackTrace();
			//https(url,params);
			return null;
		} finally {// 使用finally块来关闭输出流、输入流
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
			urlCon.disconnect();
		}
		System.out.println("=====https接受的数据为:\t" + result);
		return result;
	}

	

	public static void main(String[] args) throws Exception {
		Map<String, String> map= new HashMap<String, String>();
		map.put("laneNo", "35");
		map.put("laneType", "02");
		map.put("provinceCode", "1101");
		map.put("psamNo", "11010000000000000001");
		map.put("roadCode", "1");
		map.put("roadName", "xx高速");
		map.put("stationCode", "2");
		map.put("stationName", "xx收费站");
		map.put("stationType", "02");
		map.put("terminalNo", "110100000000");
		map.put("terminalTime", "2018-07-04 12:12:12");
		String url="https://127.0.0.1:4566/obuReplaceSecretKey/obu/test";
		System.out.println(https(url, map));
	}

}

证书生成

1 生成服务器证书库

keytool -genkey -keyalg RSA -keysize 2048 -validity 365000 -alias server -keypass 123456 -keystore server.keystore -storepass  123456 -dname "CN= 106.39.79.26:4144,OU=JL,O=JL,L=BJ,ST=BJ,C=CN"

 其中,-keyalg 指定算法,

   -keysize指定密钥大小,

   -validity指定有效期,单位为天,

   -alias  别名

   -keypass 指定私钥使用密码,

   -keystore指定密钥库名称,

   -storepass 证书库的使用密码,从里面提取公钥时需要密码

   -dname :CN拥有者名字,一般为网站名或IP+端口,如www.baidu.com,OU组织机构名 O组织名 L城市 ST州或省 C国家代码

2. 导出公钥:

    keytool -export -alias server -file server.crt -keystore server.keystore -storepass  123456

3. 将服务端证书,加入客户端的认证证书列表中       

   keytool -import -alias server -file server.crt -keystore trustOfClient.keystore -storepass  123456

4. 生成client端密钥

    keytool -genkey -keyalg RSA -keysize 2048 -validity 365000 -alias client -keypass 123456 -keystore client.keystore -storepass 123456 -dname "CN=localhost,OU=JL,O=JL,L=BJ,ST=BJ,C=CN"

5. 导出公钥:

    keytool -export -alias client -file client.crt -keystore client.keystore -storepass 123456

6. 将证书加到服务端信任列表

   keytool -import -alias server -file client.crt -keystore trustOfServer.keystore -storepass 123456

配置tomcat

修改server.xml配置文件,在server.xml配置文件加入如下信息

<Connector port="4566" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true"
           maxThreads="150" scheme="https" secure="true"
           clientAuth="true" sslProtocol="SSL"
           keystoreFile="D:\\workSoft\\cer\\server.keystore" 
           keystorePass="123456"
           truststoreFile="D:\\workSoft\\cer\\trustOfServer.keystore" 
           truststorePass="123456"
           />

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值