一、服务端
1. 生成密钥库 --- kserver.keystore 是给服务端用的,其中保存着自己的私钥
keytool -genkey -alias serverkey -keystore ./kserver.keystore -dname CN=test-server,OU=CTF,O=CTF1,L=SHH,ST=SHH,C=CN -validity 36500 -keysize 1024 -keyalg RSA -storepass 123456 -v
2. 导出密钥证书kserver.cer --- 根据私钥,导出服务端证书
keytool -export -alias serverkey -keystore ./kserver.keystore -file ./kserver.cer -storepass 123456
3. 生成服务端信任密钥库 (可以与密钥库使用同一个)
keytool -genkey -alias servertrustkey -keystore ./kservertrust.keystore -dname CN=test-server-trust,OU=CTF,O=CTF1,L=SHH,ST=SHH,C=CN -validity 36500 -keysize 1024 -keyalg RSA -storepass 123456trust -v
4. 将证书导入客户端信任库(客户端信任库在后续创建)
keytool -import -alias serverkey -file kserver.cer -keystore kclienttrust.keystore
5. 查看证书内容
keytool -list -v -keystore kserver.keystore -storepass 123456
keytool -list -v -keystore kservertrust.keystore -storepass 123456trust
二、客户端
1. 生成密钥库 --- kclient.keystore 是给服务端用的,其中保存着自己的私钥
keytool -genkey -alias clientkey -keystore ./kclient.keystore -dname CN=test-client,OU=CTF,O=CTF1,L=SHH,ST=SHH,C=CN -validity 36500 -keysize 1024 -keyalg RSA -storepass 123456 -v
2. 导出密钥证书 kclient.cer --- 根据私钥,导出服务端证书
keytool -export -alias clientkey -keystore ./kclient.keystore -file ./kclient.cer -storepass 123456
3. 生成客户端信任密钥库
keytool -genkey -alias clienttrustkey -keystore ./kclienttrust.keystore -dname CN=test-client-trust,OU=CTF,O=CTF1,L=SHH,ST=SHH,C=CN -validity 36500 -keysize 1024 -keyalg RSA -storepass 123456trust -v
此时得到如下6个文件:
4. 将证书导入服务端信任库
keytool -import -alias clientkey -file kclient.cer -keystore kservertrust.keystore
5. 查看证书内容
keytool -list -v -keystore kclient.keystore -storepass 123456keytool -list -v -keystore kclienttrust.keystore -storepass 123456trust
注:后续代码中会用到:
服务端(tomcat/weblogic):kserver.keystore、kservertrust.keystore
客户端(程序):kclient.keystore、kclienttrust.keystore
三、服务器配置
1. Tomcat 服务器配置
Tomcat安装目录/conf/server.xml 中添加,其中clientAuth=true代表开启双向验证
2. Weblogic服务器配置
最后激活重新部署。
四、自签名证书
自签名证书:对于每一个要链接的服务器,都要保存一个证书的验证副本,而且一旦服务器更换证书,所有客户端就需要重新部署这些副本。要解决这一问题可以使用openssl,或者使用第三方信任机构颁发的证书。
五、HttpsUtil工具类 - 客户端
/*** 使用httpclient4.x.x实现https双向验证*/
public class Https4client {public static void main(String[] args) throws Exception {HttpClient httpclient = getHttpClient();HttpEntity entity=null;//1.get测试
// HttpGet get = new HttpGet("https://自己服务器IP:端口/test/doget");
// HttpResponse rsp = httpclient.execute(get);//2.post测试HttpPost post = new HttpPost("https://自己服务器IP:端口/test/dopost");StringEntity stringEntity = new StringEntity("test post method!", Charset.forName("UTF-8"));post.setEntity(stringEntity);HttpResponse rsp = httpclient.execute(post);entity = rsp.getEntity();//用EntityUtils.toString()这个静态方法将HttpEntity转换成字符串,防止服务器返回的数据带有中文,所以在转换的时候将字符集指定成utf-8就可以了String result= EntityUtils.toString(entity, "UTF-8");System.out.println("-------------------------result:"+result+"-------------");if(rsp.getStatusLine().getStatusCode()==200){System.out.println(rsp.getStatusLine().getStatusCode()+"-----------success------------------");}else{System.out.println(rsp.getStatusLine().getStatusCode()+"------------------fail-----------");}}public static HttpClient getHttpClient() throws Exception{//设置http参数HttpParams params = new BasicHttpParams();HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);HttpProtocolParams.setContentCharset(params, "UTF-8");HttpProtocolParams.setUseExpectContinue(params, true);HttpConnectionParams.setConnectionTimeout(params, 5000);//连接超时HttpConnectionParams.setSoTimeout(params, 5000);//请求超时SchemeRegistry schReg = new SchemeRegistry();schReg.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));SSLSocketFactory sf = getBidirectionalSSL();schReg.register(new Scheme("https", 443, sf));PoolingClientConnectionManager pccm = new PoolingClientConnectionManager(schReg);pccm.setMaxTotal(100); // 客户端总并行链接最大数pccm.setDefaultMaxPerRoute(20); // 发送到指定主机的最大连接数DefaultHttpClient httpclient = new DefaultHttpClient(pccm, params);// //设置代理 DNS
// HttpHost proxy = new HttpHost("10.112.24.30", 8019);
// httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);return httpclient;}/*** 双向ssl 设置客户端证书* @return*/public static SSLSocketFactory getBidirectionalSSL() throws Exception {//客户端证书库,上面生成的kclient.keystoreFile certFile = new File(GetConfigUtil.getProjectConfig("ssl.client.keystore"));KeyStore ks = null;try {ks = KeyStore.getInstance("JKS");} catch (KeyStoreException e) {throw new Exception(e);}//密钥库密码 123456String password = "";try {password = GetConfigUtil.getProjectConfig("client.store.file.password");ks.load(new FileInputStream(certFile), password.toCharArray());} catch (NoSuchAlgorithmException e) {throw new Exception(e);} catch (CertificateException e) {throw new Exception(e);} catch (FileNotFoundException e) {throw new Exception(e);} catch (IOException e) {throw new Exception(e);}KeyManagerFactory kmf = null;try {kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());} catch (NoSuchAlgorithmException e) {throw new Exception(e);}try {kmf.init(ks, password.toCharArray());} catch (UnrecoverableKeyException e) {throw new Exception(e);} catch (KeyStoreException e) {throw new Exception(e);} catch (NoSuchAlgorithmException e) {throw new Exception(e);}SSLContext sslContext = null;try {sslContext = SSLContext.getInstance("TLS");} catch (NoSuchAlgorithmException e) {throw new Exception(e);}try {sslContext.init(kmf.getKeyManagers(), getTrustManager(), null);} catch (KeyManagementException e) {throw new Exception(e);} catch (Exception e) {throw new Exception(e);}SSLSocketFactory factory = new SSLSocketFactory(sslContext,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);return factory;}/*** 双向SSL 认证服务器的证书* @return* @throws Exception*/public static TrustManager[] getTrustManager() throws Exception{TrustManager[] trustManager=null;String password = "";//上面生成的kclienttrust.keystoreString publicKey = GetConfigUtil.getProjectConfig("ssl.clienttrust.keystore");if(null ==publicKey ||"".equals(publicKey)){throw new RuntimeException("信任库证书未配置");}else{//第三方机构服务器的公钥证书File publicFile = new File(publicKey);KeyStore pks = KeyStore.getInstance("JKS");password = GetConfigUtil.getProjectConfig("client.trust.file.password");pks.load(new FileInputStream(publicFile), password.toCharArray());TrustManagerFactory tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());tmf.init(pks);trustManager = tmf.getTrustManagers();}return trustManager;}}
GetConfigUtil我就不贴了吧,还是要自己动动脑子的,不能彻底无脑CV流~~
算了我还是分享出来吧
项目地址:https://gitee.com/defense-of-the-anciant2/market-purchase