Spring实现HTTPS双向认证

目录

前言

一、单向认证和双向认证

二、创建keyStore和trustStore

三、服务端配置

四、客户端配置 

总结

参考链接


前言

本篇博客讲的主要是双向认证,通过一些简单案例来展示双向认证的配置过程。有关单向认证和一些https配置,可以看看我的这篇博客,只有了解清楚单向认证之后,那么双向认证理解更加简单,因为双向认证基于单向认证配置,所以建议在做https双向认证之前,先把https单向认证搞清楚:

Spring实现HTTPS方式访问服务(单向认证)_明天再去学习的博客-CSDN博客

 


一、单向认证和双向认证

1、单向认证

单向认证十分简单,就是在服务端配置证书,客户端在向服务端发送请求时,服务端会发送一份自己的证书,由客户端进行验证,只要客户端通过验证,那么就能建立https链接。

2、双向认证

双向认证相比于单向认证多了一个步骤,那就是客户端发送请求时校验服务端的证书的同时,客户端也需要发送一份自己的证书给服务端进行校验,只有双方的证书在对方那里校验通过之后,才能建立起https链接。

二、创建keyStore和trustStore

1、keyStore与trustStore的作用

keyStore:

  • keyStore是一个可以存储密钥、密钥对或证书的存储库。密钥:只有一个钥,一般是对称加密时使用;密钥对:包含公钥和私钥,一般是非对称加密时使用。
  • keyStore文件的类型可以是JSK、PKCS12、JCEKS。JSK(Java Key Store)可以存储密钥对和证书;PKCS12、JCEKS都可以存储密钥、密钥对、证书。
  • 在创建keyStore文件时,可以为keyStore设置密码。
  • 密钥、密钥对、证书在keyStore统称为key,每一个key通过alias(别名)区分。key也可以设置密码(具体体现在keytool创建keyStore和trustStore时),keyStore可以存储多对key。
  • 通过keytool成功往一个keyStore文件添加密钥对后,可以从该keyStore中获取到私钥、证书以及公钥(公钥主要以证书的形式存放)。

trustStore:

  •  trustStore中保存的是一些可信任的证书
  • trustStore文件的类型可以是JSK、PKCS12、JCEKS。JSK(Java Key Store)可以存储密钥对和证书;PKCS12、JCEKS都可以存储密钥、密钥对、证书。

2、创建服务端keyStore和客户端trustStore(以下指令均在控制台执行)

注意:由于只是本地简单配置双向认证,涉及到的证书将由工具keytool生成,真正生产环境下的证书,将有认证过的CA机构去生成。

创建服务端keyStore

keytool -genkey -alias serverkey -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -keystore serverkeystore.p12 -storepass 123456 -ext san=ip:127.0.0.1,dns:localhost

导出服务端证书

keytool -exportcert -keystore serverkeystore.p12 -alias serverkey -storepass 123456 -rfc -file server-certificate.pem

将服务端证书添加到客户端trustStore中 

keytool -import -trustcacerts -file server-certificate.pem -keypass 123456 -storepass 123456 -keystore clienttruststore.jks

3、创建客户端keyStore和服务端trustStore 

 创建客户端keyStore

keytool -genkey -alias client -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -keystore clientKeystore.p12 -storepass 123456 -ext san=ip:127.0.0.1

导出客户端证书

keytool -exportcert -keystore clientKeystore.p12 -alias client -storepass 123456 -rfc -file client-certificate.pem

将客户端证书添加到服务端trustStore中 

keytool -import -trustcacerts -file client-certificate.pem -keypass 123456 -storepass 123456 -keystore serverTruststore.jks

4、生成结果

 

在后续实践中,我们需要用到的是 serverKeyStore、serverTrustStore、clientKeyStore、clientTrustStore

 

三、服务端配置

1、将serverKeyStore、serverTrustStore存放在resource目录下

2、application.yml配置如下

server:
  port: 7050
  ssl:
    key-store: classpath:serverKeyStore.p12
    key-store-password: 123456
    key-store-type: PKCS12
    key-alias: serverKey
    client-auth: need
    trust-store: classpath:serverTrustStore.jks
    trust-store-password: 123456
    trust-store-type: JKS
  • key-store:用于指定你的keyStrore文件
  • key-store-type:指定你的文件的类型,在上面说过,keyStore的类型可以是JKS、PKCS12、JCEKS
  • key-store-password:就是你在通过keytool创建keyStore时指定的密码
  • key-alias: 指定使用哪一个key
  • client-auth:开启客户端验证,即需要验证客户端证书,服务端开启双向认证的开关
  • trust-store:用于指定你的trustStrore(信任库)文件,客户端证书校验将在此处进行
  • trust-store-type:指定你的文件的类型,在上面说过,trustStore的类型可以是JKS、PKCS12、JCEKS
  • trust-store-password:就是你在通过keytool创建trustStore时指定的密码

至此,服务端https双向认证配置到此处结束,接下来是客户端的配置

 

四、客户端配置 

1、将clientKeyStore、clientTrustStore存放在resource目录下:

 

2、导入以下依赖:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.6</version>
</dependency>

 

3、进行RestTemplate配置:

@Slf4j
@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory httpComponentsClientHttpRequestFactory) {
        RestTemplate restTemplate = new RestTemplate(httpComponentsClientHttpRequestFactory);
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        return restTemplate;
    }

    @Bean("httpComponentsClientHttpRequestFactory")
    public ClientHttpRequestFactory httpComponentsClientHttpRequestFactory() throws IOException, UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
        final String allPassword = "123456";
        TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
        SSLContext sslContext = SSLContextBuilder
                .create()
                .loadKeyMaterial(new ClassPathResource("clientKeystore.p12").getURL(),
                        allPassword.toCharArray(), allPassword.toCharArray())
                .loadTrustMaterial(new ClassPathResource("clientTruststore.jks").getURL(), allPassword.toCharArray())
                .loadTrustMaterial(null, acceptingTrustStrategy)
                .build();
        HttpClient client = HttpClients.custom()
                .setSSLContext(sslContext)
                .build();
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(client);
        // INSTANCE 忽略域名检查,证书中的域名与请求的域名不匹配时,验证通过, 不建议开启该功能,因为存在安全问题
       /*SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
        CloseableHttpClient httpclient = HttpClients
                .custom()
                .setSSLSocketFactory(sslConnectionSocketFactory)
                .setSSLHostnameVerifier(new NoopHostnameVerifier())
                .build();
        requestFactory.setHttpClient(httpclient);*/
        return requestFactory;
    }

}

 4、通过RestTempate进行接口调用,客户端能够与开启双向认证后的服务端进行连接访问。

至此,客户端的配置也完成了 。


总结

双向配置的精髓就是,客户端也需要配置自己的证书,在发送请求的同时,将自己的证书发送给服务端,让服务端去验证证书,所以,搞清楚双向认证配置之前,一定要先弄清楚单向认证配置,以达事半功倍。

参考链接

一文读懂Https的安全性原理、数字证书、单项认证、双项认证等 - 知乎

百度安全验证 

 

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值