程序员开发实例大全宝库

网站首页 > 编程文章 正文

Https双向认证,系统间通讯的双向认证

zazugpt 2024-08-12 03:23:58 编程文章 32 ℃ 0 评论

1.背景

现在公司系统较多,多系统间需要进行通讯,已经实现了https单项认证,现在为了保证通讯的安全,需要实现https双向认证,让系统间通讯更安全。

2.问题

当时拿到这个问题,第一时间去网上百度https双向认证的案例,试了好多种,有单项认证的实现,还有双向认证基于浏览器端的访问,对于两个系统之间的https双向认证很少,自己也浪费了好多时间没有成功,于是,下定决心,先把https双向认证的原理搞清楚,懂了原理后,解决起来问题就方便了,下面附上https单项认证和双向认证的原理图




通过图片可知,https单项认证是客户端对服务端的认证,双向认证是在此基础上加了服务端对客户端的认证!

3.前提准备

1. 多个springboot项目,以两个springboot项目为例,这里暂且叫Client项目,Server项目。

2. Client项目所在的服务器,Client.p12(客户端证书库) ,Client.cer(客户端公钥);

Server项目所在的服务器,Server.p12(服务端证书库),Server.cer(服务端公钥);

4.实现步骤

1. 创建springboot项目,Client ,Server 此处,请自行百度创建如何创建springboot项目。

2. 使用jdk自带的keytool工具,生成Client和Server端相应的证书,步骤如下:

a. Client端证书生成步骤:

1.生成客户端 Client.p12文件

keytool -genkey -v -alias Client -keyalg RSA -storetype PKCS12 -keystore C:\D\jdk1.8.0_161\Client.p12

设置密码: lq123456 注意事项:生成证书,您的名字与姓氏一项,应该填写服务器的ip(此处应该是域名,但是没有域名,故此处填写服务器ip) 2 . 导出客户端公钥Client.cer 文件 keytool -keystore C:\D\jdk1.8.0_161\Client.p12 -export -alias Client -file C:\D\jdk1.8.0_161\Client.cer

b. Server端证书生成步骤

1. 生成服务端Server.p12文件

keytool -genkey -v -alias Server -keyalg RSA -storetype PKCS12 -keystore C:\D\jdk1.8.0_161\Server.p12

设置密码: lq123456 注意事项:生成证书,您的名字与姓氏一项,应该填写服务器的ip(此处应该是域名,但是没有域名,故此处填写服务器ip) 2. 导出服务端公钥Server.cer 文件

keytool -keystore C:\D\jdk1.8.0_161\Server.p12 -export -alias Server -file C:\D\jdk1.8.0_161\Server.cer

c. 将Client端和Server端的公钥文件(.cer文件)导入双方系统的jre运行环境的cacerts证书库

1. 将客户端公钥导入的服务端jdk信任库 keytool -import -file Client.cer -keystore C:\D\jdk1.8.0_161\jre\lib\security\cacerts –v

2. 将服务端公钥导入到客户端的jdk信任库 keytool -import -file Server.cer -keystore C:\D\jdk1.8.0_161\jre\lib\security\cacerts –v

3. 将客户端公钥导入到服务端Server.p12证书库

keytool -import -v -file C:\D\jdk1.8.0_161\Client.cer -keystore C:\D\jdk1.8.0_161\server.p12

注意事项:此处导入的密码为changeit,默认密码

至此,证书生成完成,证书库导入完成!

d. 代码实现

1.Server端

第一步:在application.properties中添加如下配置:包括本地证书库和受信任证书配置


server.port=8090

server.address=10.119.165.171

server.ssl.key-store=classpath:server.p12

server.ssl.key-store-password=lq123456

server.ssl.key-alias=server

server.ssl.keyStoreType=JKS



server.ssl.trust-store=classpath:server.p12

server.ssl.trust-store-password=lq123456

server.ssl.client-auth=need

server.ssl.trust-store-type=JKS

server.ssl.trust-store-provider=SUN


server.port=8090

server.address=10.119.165.171

server.ssl.key-store=classpath:server.p12

server.ssl.key-store-password=lq123456

server.ssl.key-alias=server

server.ssl.keyStoreType=JKS



server.ssl.trust-store=classpath:server.p12

server.ssl.trust-store-password=lq123456

server.ssl.client-auth=need

server.ssl.trust-store-type=JKS

server.ssl.trust-store-provider=SUN


2. Client端

第一步:在application.properties中添加如下配置:


server.port=8091

server.address=10.119.165.171

server.ssl.key-store=classpath:client.p12

server.ssl.key-store-password=lq123456

server.ssl.key-alias=client

server.ssl.keyStoreType=JKS


第二步

单元测试


package com.example.client;


import java.io.FileInputStream;

import java.security.KeyStore;

import java.security.SecureRandom;

import javax.net.ssl.KeyManager;

import javax.net.ssl.KeyManagerFactory;

import javax.net.ssl.SSLContext;

import javax.net.ssl.TrustManager;

import javax.net.ssl.TrustManagerFactory;

import org.apache.http.HttpEntity;

import org.apache.http.client.methods.CloseableHttpResponse;

import org.apache.http.client.methods.HttpGet;

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;

import org.apache.http.impl.client.CloseableHttpClient;

import org.apache.http.impl.client.HttpClients;

import org.apache.http.util.EntityUtils;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.test.context.junit4.SpringRunner;


/**

* @author lucasliang

* @date 04/03/2019 2:13 下午

* @Description

*/

@SpringBootTest(classes = {Client1ApplicationTests.class})

@RunWith(SpringRunner.class)

public class P12CertTest {


private final static String TEST_URL = "https://10.119.165.171:8090/server/hello";


@Test

public void getHKVesselTrip() throws Exception {

KeyStore clientStore = KeyStore.getInstance("PKCS12");

clientStore

.load(new FileInputStream("C:\\D\\jdk1.8.0_161\\shuangxiang\\client_original.p12"),

"lq123456".toCharArray());


KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

kmf.init(clientStore, "lq123456".toCharArray());

KeyManager[] kms = kmf.getKeyManagers();

TrustManagerFactory tmf = TrustManagerFactory

.getInstance(TrustManagerFactory.getDefaultAlgorithm());


KeyStore trustStore = KeyStore.getInstance("JKS");

trustStore.load(new FileInputStream("C:\\D\\jdk1.8.0_161\\jre\\lib\\security\\cacerts"),

"changeit".toCharArray());

tmf.init(trustStore);

TrustManager[] tms = tmf.getTrustManagers();

SSLContext sslContext = SSLContext.getInstance("TLS");

sslContext.init(kms, tms, new SecureRandom());

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,

SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

try {

HttpGet httpget = new HttpGet(TEST_URL);

System.out.println("executing request" + httpget.getRequestLine());

CloseableHttpResponse response = httpclient.execute(httpget);

try {

HttpEntity entity = response.getEntity();

if (entity != null) {

System.out.println(EntityUtils.toString(entity));

}

} finally {

response.close();

}

} finally {


httpclient.close();

}


}


}



此时,Client端发送请求到Server端,请求成功,https双向认证完成!

5. 心得

凡事搞懂原理,事半功倍

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表