Spring实现HTTPS双向认证

落日映苍穹つ 2023-10-02 23:22 23阅读 0赞

目录

前言

一、单向认证和双向认证

二、创建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

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

导出服务端证书

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

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

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

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

创建客户端keyStore

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

导出客户端证书

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

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

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

4、生成结果

f7fab22161764b6fa614e8c910a652d6.png

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

三、服务端配置

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

9fbc9ab2debe4cae85ca19e3cff05b1a.png

2、application.yml配置如下

  1. server:
  2. port: 7050
  3. ssl:
  4. key-store: classpath:serverKeyStore.p12
  5. key-store-password: 123456
  6. key-store-type: PKCS12
  7. key-alias: serverKey
  8. client-auth: need
  9. trust-store: classpath:serverTrustStore.jks
  10. trust-store-password: 123456
  11. 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目录下:

9e9af135d5a64bf987131403d4317db2.png

2、导入以下依赖:

  1. <dependency>
  2. <groupId>org.apache.httpcomponents</groupId>
  3. <artifactId>httpclient</artifactId>
  4. <version>4.5.6</version>
  5. </dependency>

3、进行RestTemplate配置:

  1. @Slf4j
  2. @Configuration
  3. public class RestTemplateConfig {
  4. @Bean
  5. public RestTemplate restTemplate(ClientHttpRequestFactory httpComponentsClientHttpRequestFactory) {
  6. RestTemplate restTemplate = new RestTemplate(httpComponentsClientHttpRequestFactory);
  7. restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
  8. return restTemplate;
  9. }
  10. @Bean("httpComponentsClientHttpRequestFactory")
  11. public ClientHttpRequestFactory httpComponentsClientHttpRequestFactory() throws IOException, UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
  12. final String allPassword = "123456";
  13. TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
  14. SSLContext sslContext = SSLContextBuilder
  15. .create()
  16. .loadKeyMaterial(new ClassPathResource("clientKeystore.p12").getURL(),
  17. allPassword.toCharArray(), allPassword.toCharArray())
  18. .loadTrustMaterial(new ClassPathResource("clientTruststore.jks").getURL(), allPassword.toCharArray())
  19. .loadTrustMaterial(null, acceptingTrustStrategy)
  20. .build();
  21. HttpClient client = HttpClients.custom()
  22. .setSSLContext(sslContext)
  23. .build();
  24. HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(client);
  25. // INSTANCE 忽略域名检查,证书中的域名与请求的域名不匹配时,验证通过, 不建议开启该功能,因为存在安全问题
  26. /*SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
  27. CloseableHttpClient httpclient = HttpClients
  28. .custom()
  29. .setSSLSocketFactory(sslConnectionSocketFactory)
  30. .setSSLHostnameVerifier(new NoopHostnameVerifier())
  31. .build();
  32. requestFactory.setHttpClient(httpclient);*/
  33. return requestFactory;
  34. }
  35. }

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

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


总结

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

参考链接

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

百度安全验证

发表评论

表情:
评论列表 (有 0 条评论,23人围观)

还没有评论,来说两句吧...

相关阅读