私有CA搭建并将HTTPS应用于Tomcat、Springboot

目录

1 CA概念

2 HTTPS过程

3 环境说明

4 搭建私有CA

4.1 环境准备

4.2 搭建CA中心

4.3 操作错误从新来过

5 浏览器证书配置

6 创建服务器证书

6.1 环境准备

6.2 创建服务器证书

6.2 配置证书

7 将CA证书导入JDK

8 创建Tomcat服务器证书

9 Tomcat的HTTPS配置

9.1 单向认证

9.2 双向认证

10 SpringBoot的HTTPS配置

10.1 单向认证

10.2 双向认证

11 SpringCloud openfeign服务调用

11.1 测试环境下,信任所有的证书

11.2 生产环境下,信任特定CA的证书

 


1 CA概念

万事不觉问度娘。

2 HTTPS过程

 

密码库保存的是自己的自己私钥、自己的公钥、自己或别人的证书。信任库中保存的是CA机构的证书,作用是新人CA机构颁发的证书,也就是说只要是该机构颁发的证书,都能被认证为有效,不需要在密码库中添加被验证者的证书。

如果只是1个tomcat服务和浏览器之间使用HTTPS,那么只需要在tomcat的密码库添加浏览器的证书,在浏览器密码库中添加tomcat的证书,那么就可以在浏览器中使用https进行访问了。网上博客大部分关于Tomcat配置HTTPS都是基于这一点进行配置的。推荐,https://blog.csdn.net/dwyane__wade/article/details/80350548

如果tomcat服务比较多,那么每一个都需要像上面一样来回添加证书,比较繁琐,这个时候,使用CA机构进行认证时比较方便的。这也时,私有CA搭建以及使用的过程。下面讲解都是关于该方案进行的。

当然,只是用于tomcat、springboot测试,所有的服务强行用一个证书,也是可以的,那就要求所有服务域名都是一致的。

建议搭建一个CA中心,使用ssl认证的组件都会用到,例如,zk、kafka、nginx的https、tomcat的https、springboot的https等。

1 创建CA中心

2 创建Tomcat服务器秘钥库
3 创建Tomcat服务器信任库,并将CA证书导入信任库
4 生产需要签名的请求文件
5 将请求文件发送给CA中心
6 CA中心根据请求文件签名
7 CA中心将签名后的文件发回
8 将签名后的证书导入到Tomcat服务器秘钥库
9 将CA证书导入到建Tomcat服务器秘钥库

3 环境说明

ip

hostname

用途

系统

192.168.65.51

spring1

CA中心

Centos虚拟机

192.168.65.52

spring2

服务器

Centos虚拟机

192.168.65.1

 

浏览器

Windows主机

在各个机器上配置host文件。

4 搭建私有CA

参考https://www.cnblogs.com/bigdevilking/p/9434444.html

4.1 环境准备

spring1需要openssl工具,最好是升级到最新的。

4.2 搭建CA中心

Step1:配置一个自己的CA认证中心。

[root@spring1 ~]# vi /etc/pki/tls/openssl.cnf +172

basicConstraints=CA:FALSE # 把FALSE改成TRUE 把本机变成CA认证中心

Step2:配置认证中心,生成私钥与根证书。

[root@ca ~]# /etc/pki/tls/misc/CA -newca

 

 

这里配置了CA认证中心 ,在里面就生成了CA认证根证书的私钥 ,在配置完结束之后 ,就会生成一个根证书,这个根证书中有这证书的公钥。到此CA认证中心就搭建好了。

查看生成的CA根证书 :

[root@spring1 CA]# cat /etc/pki/CA/cacert.pem

Certificate:

    Data:

        Version: 3 (0x2)

        Serial Number: 1 (0x1)

    Signature Algorithm: sha256WithRSAEncryption

        Issuer: C=CN, ST=FJ, O=FF, OU=BD, CN=spring1

        Validity

            Not Before: Dec 16 09:23:56 2019 GMT

            Not After : Dec 15 09:23:56 2022 GMT

        Subject: C=CN, ST=FJ, O=FF, OU=BD, CN=spring1

        Subject Public Key Info:

            Public Key Algorithm: rsaEncryption

                Public-Key: (2048 bit)

                Modulus:

                    00:d9:8b:77:09:17:7d:ce:4b:f0:89:b1:f4:79:8c:

                    54:20:64:2a:9b:65:32:db:aa:0c:e2:85:f0:36:bd:

                    74:06:27:c9:4d:52:2c:b9:64:50:9a:da:5c:57:ef:

                    d5:cb:d0:52:42:a9:58:d3:1d:e5:48:65:d2:4e:21:

                    9a:df:42:fc:a4:80:fb:43:62:73:db:04:1e:06:3a:

                    c3:58:29:e9:42:90:33:9f:d1:6e:f8:3a:c8:4f:ad:

                    26:4d:f6:62:23:b6:7a:ce:36:54:90:5a:f7:ce:0f:

                    24:cb:2e:bd:d7:bd:c3:c7:1a:4e:3c:49:45:63:3b:

                    f4:c3:44:b8:0a:33:3e:4b:85:70:4f:0d:bd:41:c0:

                    bf:67:46:4e:eb:26:ea:97:4f:03:d0:99:69:32:7e:

                    3b:50:7a:15:b2:70:ee:c2:a8:4c:66:ca:f3:da:a5:

                    a8:82:21:76:ad:6c:40:ce:2d:bf:7f:3e:a8:61:05:

                    3e:a8:c7:1a:5e:bf:e3:d8:79:f9:bb:91:b0:4a:58:

                    0c:02:3c:ca:6c:cd:81:c3:bf:2a:73:10:33:f5:75:

                    76:d0:71:6f:04:8e:10:c2:4a:a9:13:92:a5:3e:73:

                    46:fb:d9:1b:95:02:85:e6:64:41:e5:70:c0:c5:cf:

                    ad:7e:ce:4b:ed:56:41:dc:b4:00:10:47:91:1f:6b:

                    20:39

                Exponent: 65537 (0x10001)

        X509v3 extensions:

            X509v3 Subject Key Identifier:

                F3:D6:D0:8A:A5:B9:B2:7D:DF:93:ED:0D:27:9F:8F:D6:B0:80:0B:94

            X509v3 Authority Key Identifier:

                keyid:F3:D6:D0:8A:A5:B9:B2:7D:DF:93:ED:0D:27:9F:8F:D6:B0:80:0B:94

 

            X509v3 Basic Constraints:

                CA:TRUE

    Signature Algorithm: sha256WithRSAEncryption

         5a:12:fb:6c:35:c3:37:76:74:8b:d8:4d:b4:c1:2c:35:57:01:

         48:a2:f0:77:44:d6:37:49:37:21:ba:69:0e:59:de:44:bd:b1:

         12:85:46:20:61:27:46:b8:b2:02:f1:c2:2f:42:9e:84:e0:f6:

         85:0a:88:df:8c:fb:a2:d9:73:ff:89:d0:f3:ee:43:83:0e:a9:

         aa:3a:fb:f5:8d:82:76:0e:a0:da:0f:8b:23:5e:f6:86:6d:6d:

         b1:f3:4a:5e:0c:aa:fe:10:3a:87:bb:39:b7:03:32:23:d8:04:

         f2:be:5f:ce:5a:65:8e:a0:4a:2b:ed:df:17:fa:a6:99:e5:91:

         de:80:a6:96:54:7d:bc:0a:93:8b:2b:dc:7d:58:33:71:27:03:

         5c:9d:aa:5e:7c:6e:e3:bf:61:92:ea:0c:b5:38:23:ce:b0:c6:

         b6:20:5f:1d:d1:fa:81:2d:95:65:af:1e:cf:77:85:53:9a:2a:

         eb:e9:ff:96:f7:9e:fa:cc:05:fe:3a:a4:24:22:fb:5a:e8:d1:

         9a:f0:7a:3f:1b:3f:b0:71:e0:31:45:37:3e:80:2d:27:f5:6a:

         d9:da:9d:ee:dd:d8:6d:af:05:88:7e:61:5a:fe:2a:40:25:ff:

         56:f3:42:d1:3f:78:6d:77:0f:5b:1b:52:17:a2:5b:f6:80:3b:

         cf:43:f4:f0

-----BEGIN CERTIFICATE-----

MIIDVzCCAj+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQGEwJDTjEL

MAkGA1UECAwCRkoxCzAJBgNVBAoMAkZGMQswCQYDVQQLDAJCRDEQMA4GA1UEAwwH

c3ByaW5nMTAeFw0xOTEyMTYwOTIzNTZaFw0yMjEyMTUwOTIzNTZaMEYxCzAJBgNV

BAYTAkNOMQswCQYDVQQIDAJGSjELMAkGA1UECgwCRkYxCzAJBgNVBAsMAkJEMRAw

DgYDVQQDDAdzcHJpbmcxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA

2Yt3CRd9zkvwibH0eYxUIGQqm2Uy26oM4oXwNr10BifJTVIsuWRQmtpcV+/Vy9BS

QqlY0x3lSGXSTiGa30L8pID7Q2Jz2wQeBjrDWCnpQpAzn9Fu+DrIT60mTfZiI7Z6

zjZUkFr3zg8kyy69173DxxpOPElFYzv0w0S4CjM+S4VwTw29QcC/Z0ZO6ybql08D

0JlpMn47UHoVsnDuwqhMZsrz2qWogiF2rWxAzi2/fz6oYQU+qMcaXr/j2Hn5u5Gw

SlgMAjzKbM2Bw78qcxAz9XV20HFvBI4QwkqpE5KlPnNG+9kblQKF5mRB5XDAxc+t

fs5L7VZB3LQAEEeRH2sgOQIDAQABo1AwTjAdBgNVHQ4EFgQU89bQiqW5sn3fk+0N

J5+P1rCAC5QwHwYDVR0jBBgwFoAU89bQiqW5sn3fk+0NJ5+P1rCAC5QwDAYDVR0T

BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAWhL7bDXDN3Z0i9hNtMEsNVcBSKLw

d0TWN0k3IbppDlneRL2xEoVGIGEnRriyAvHCL0KehOD2hQqI34z7otlz/4nQ8+5D

gw6pqjr79Y2Cdg6g2g+LI172hm1tsfNKXgyq/hA6h7s5twMyI9gE8r5fzlpljqBK

K+3fF/qmmeWR3oCmllR9vAqTiyvcfVgzcScDXJ2qXnxu479hkuoMtTgjzrDGtiBf

HdH6gS2VZa8ez3eFU5oq6+n/lvee+swF/jqkJCL7WujRmvB6Pxs/sHHgMUU3PoAt

J/Vq2dqd7t3Yba8FiH5hWv4qQCX/VvNC0T94bXcPWxtSF6Jb9oA7z0P08A==

-----END CERTIFICATE-----

查看根证书的私钥 :

[root@ca ~]# vim /etc/pki/CA/private/cakey.pem    # CA认证下根证书的私钥

-----BEGIN ENCRYPTED PRIVATE KEY-----                                                        

MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQInT7FONSpFscCAggA

MBQGCCqGSIb3DQMHBAi1VvUPV2DgKwSCBMjHCgsNdj+BrCSvkFaHtX6iGaitR7WJ

bBEWrarlcGGVdAHYW6Hwpb548FXXLhXagTcU1gj6EP8ylJ5+ZsQtXM6B/HlzX+c6

TKTdS4QBotFUqb2BRZkN0Une4k17RxDNW6Por4OEEk4hs6xpr0up5ihV5L2H3JWw

Q+9zL8SUflXBXOsrdPFKzs5iE8u7zJgff1xR9W11IEXBs3ScqRQ6iuFJjebAam+7

BkHkpXeV0hOp7BjjJKMUg9wUAy7ar7kVJnGR5rq5FAD1r786J01jmc6V+yRkiL8g

l6wrTOyVvunt+9qc+f7YkjwN9TZ1Fb4pTCIjbtziKmkrHKy/xQX3hMICgQbwMuFz

/QlOWBrBTv14nyZpfg3UlFo1PacAG7l5prLO34K/6KqnvVSMFRw0m513eWVs5FUf

2DVjIqDhBVxnxRaX+S+FWjoGsptXpXNKExqhlGkbv/bZqLbBA0crotXKgG1I7qqI

zSrKKynqjf1MUF7z2bt4AsAdpJgdRRT94+lKRxqrnCVnhF76KXEpAO98DNLVHMk9

xRI7xTKv32GnSgE5YraYBLoCXrhGoqM/6eMy70mAWleRE6JId/9ZiPQO23cme8rJ

zzjAFgH9AtewXc4crG2yfVtqZ0pxJBfY9b20E730x5enIOjNEQ1cWAT4yk0KkliJ

dv4lq9xwBQnvsPIs3hAI4JEDMrf+VQohhZ/EO5puAoSopAKppdJAq8Mt5RuXgEqT

n3sd1WV6i/Crszvyjdhsdpms3HECpV2FDQyheGN1Ms7Evl4+T2LMjQSvimLRaM4G

kxg+a/AqGgmTkxXh5mOAO4/jhNIr/xFTA6FjlEtzVMbqBOFFmWnOlmbr6Ik/iDxn

AD2Ebqeoyj3t/q+najLHFBANOtboOISgCQFWqgIWNW5W2wdCTHVDqf/18v2eMKXo

IYiNV3IwuzzXud2iFAsLnx1i136BwPXJr0Q2BxfI5k9+7JcPVKvtf8rzjes1a89j

cnbepAepeHXCm8JFAQIFrWJI5FaInXf+kTlr/HrFlI7XxNTk49EugAq702EE75rZ

EAenZrEj0dV4uOay+p+ay3mK6774FO5RxM6oZWzjbmydtTcXjrqqRqJn5WDjREfB

XrsQnCbMPoHaCrrUpZOIyZJu6wNgAdiXI0CkPfWBAXHireBMzmS6iICE3C5dZ3k+

XoXiglggCuGw4M/cIdOOOPKFetrMe541k6w+p1ZQrK1jxJfKOb7xaR1a4CBzLh5s

amt6sDqr2AR60e7uBpr8R2FKmKtj8AVVL4UZFvxiU532vMB4zWjsvjluXdCXTzzp

Wzzw6TXs+pQvYRnJNqqTu6tUZtmZiA+RFlfmyi0wfV5MbL6UOE4SNQuMJCFGiXE4

gj2zKhb4jP/zgDEeppaE/RqAQ14zu0keTEp8srnZUrMakcBjSrX6mSdHddjtHOHJ

k2bjsGJp7Iakx5H90UAQ4J5sgQ2cejpgTPpnEeLaij6iKz7Do4+IC5Lk8KkDsCYn

VuMtxid3J8MTmTkRdpJCRK6KJNtf23AS1Uovxvek7Yg67PtKiAI55uXfLXdvxdfH

DpT+LpxGGi1dYB7Y2kA61H8d3tFLcs8istSezdlTwVY6e+aE2Q6B+BOINECGRCSY

jCM=

-----END ENCRYPTED PRIVATE KEY-----

4.3 操作错误从新来过

 

红色表示是需要的文件或者文件夹。执行下面的脚本,然后再执行4.2中的步骤。

cd /etc/pki/CA

rm -rf *

mkdir certs

mkdir crl

touch index.txt

mkdir newcerts

mkidr private

echo “01” > serial

5 浏览器证书配置

Step1 将证书转成crt安装格式

[root@spring2 ~]# openssl x509 -outform der -in cacert.pem -out cacert.crt

Step2 浏览器安装证书

从服务器上下载下来:

 

安装证书:Internet选项>内容>证书>受信任的根证书颁发机构>导入

 

 

 

 

 

 

6 创建服务器证书

使用http工具,进行验证。最后也给出了使用tomcat的配置方式。

6.1 环境准备

在spring2中安装httpd。

[root@spring2 ~]# yum -y install httpd

[root@spring2 ~]# vi /etc/httpd/conf/httpd.conf

// 把 #ServerName www.example.com:80 改成 ServerName spring2:80

[root@spring2 ~]# systemctl start httpd

6.2 创建服务器证书

Step1:生成一个私钥公钥:

[root@spring2 ~]# openssl genrsa -des3 -out /etc/httpd/conf.d/server.key

 

Step2 生成请求文件:

[root@spring2 ~]# openssl req -new -key /etc/httpd/conf.d/server.key -out /etc/httpd/conf.d/server.csr    
# 注意后期添加的国家,省,城市等信息要和CA保持一致

Step3 将证书请求文件发给CA服务器:

[root@spring2 ~]# scp /etc/httpd/conf.d/server.csr root@spring1:/root/ca   

Step4 CA认证中心进行CA签名:这里的认证中心进行的签名是用自己的私钥进行签名,在颁发之前,CA认证中心会使用自己的公钥进行加密。

[root@spring1 ~]# openssl ca -keyfile /etc/pki/CA/private/cakey.pem -cert /etc/pki/CA/cacert.pem -in /root/ca/server.csr -out /root/ca/server.crt

 

Step5 发布证书

[root@spring1 ~]# scp /root/ca/server.crt root@spring2:/etc/httpd/conf.d/server.crt

6.2 配置证书

6.2.1 配置HTTPSweb服务器

[root@spring2 ~]# yum -y install mod_ssl    # 安装SSL模块

[root@spring2 ~]# vi /etc/httpd/conf.d/ssl.conf

# SSLCertificateFile /etc/pki/tls/certs/localhost.crt 把路径改成/etc/httpd/conf.d/server.crt

# SSLCertificateKeyFile /etc/pki/tls/private/localhost.key 把路径改成/etc/httpd/conf.d/server.key

[root@spring2 ~]# systemctl restart httpd

Enter SSL pass phrase for 192.168.94.111:443 (RSA) : ******   # 私钥密码

6.2.2 测试

[root@spring2 ~]# netstat -antup | grep 443

tcp6       0      0 :::443                  :::*                    LISTEN      1634/httpd   

 

以上是关于CA相关的操作,openssl的使用、颁发证书的流程以及测试。使用JDK的方式有点点不同。

7 将CA证书导入JDK

Step1 下载CA中心证书到Windows本地为F:/ca/cacert.pem

Step2 将证书导入JDK的证书库中。标记为jdk安装路径。密码默认为changeit。

keytool -import -alias ca-spring1 -file F:/ca/cacert.pem -keystore F:/work/program/Java/jre/lib/security/cacerts -storepass changeit

8 创建Tomcat服务器证书

Step1 创建Tomcat服务器秘钥库

Step2 创建Tomcat服务器信任库,并将CA证书导入信任库

Step3 生产需要签名的请求文件

Step4 将请求文件发送给CA中心

Step5 CA中心根据请求文件签名

Step6 CA中心将签名后的文件发回

Step7 将签名后的证书导入到Tomcat服务器秘钥库

Step8 将CA证书导入到建Tomcat服务器秘钥库

#查看jdk生成的证书

keytool -list -keystore tomcat.keystore.jks -storepass nemonemo

 

#Step1 创建Tomcat服务器秘钥库,标记部分要和CA证书中的一致

keytool -genkey -alias tomcat -keypass nemonemo -keyalg RSA -keysize 2048 -validity 365 -keystore tomcat.keystore.jks -storepass nemonemo -dname "C=CN, ST=FJ, L=FZ, O=FF, OU=BD, CN=spring3"

 

#Step2 创建Tomcat服务器信任库

keytool -import -alias ca-spring1 -keypass nemonemo -file cacert.pem -keystore spring1.truststore.jks -storepass nemonemo

 

#Step3 生产需要签名的请求文件

keytool -certreq -alias tomcat -file tomcat.csr -keystore tomcat.keystore.jks -storepass nemonemo

 

#Step4 将请求文件发送给CA中心

scp tomcat.csr root@spring1:/root/ca/

 

#Step5 CA中心根据请求文件签名

openssl x509 -req -CAkey /etc/pki/CA/private/cakey.pem -CA /etc/pki/CA/cacert.pem -CAcreateserial -in /root/ca/tomcat/tomcat.csr -out /root/ca/tomcat/tomcat.crt -passin pass:nemo

 

#Step6 CA中心将签名后的文件发回

scp tomcat.crt nemo@spring3:/home/nemo/ca/

 

#Step7 将签名后的证书导入到Tomcat服务器秘钥库,别名要与step1中相同

keytool -import -alias tomcat -file tomcat.crt -keystore tomcat.keystore.jks -storepass nemonemo

 

#Step8 将CA证书导入到建Tomcat服务器秘钥库

keytool -import -alias ca-spring1 -file cacert.pem -keystore tomcat.keystore.jks -storepass nemonemo

 

9 Tomcat的HTTPS配置

9.1 单向认证

<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"

maxThreads="150" SSLEnabled="true" scheme="https" secure="true"

clientAuth="false" sslProtocol="TLS"

keystoreFile="/home/nemo/ca/tomcat.keystore.jks" keystorePass="nemonemo"

truststoreFile="/home/nemo/ca/spring1.truststore.jks" truststorePass="nemonemo"

/>

9.2 双向认证

<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"

maxThreads="150" SSLEnabled="true" scheme="https" secure="true"

clientAuth="true" sslProtocol="TLS"

keystoreFile="/home/nemo/ca/tomcat.keystore.jks" keystorePass="nemonemo"

truststoreFile="/home/nemo/ca/spring1.truststore.jks" truststorePass="nemonemo"

/>

10 SpringBoot的HTTPS配置

10.1 单向认证

server.ssl.keyStoreType=JKS
server.ssl.key-store=/home/nemo/ca/tomcat.keystore.jks
server.ssl.key-store-password=nemonemo
server.ssl.key-alias=tomcat

10.2 双向认证

server.ssl.keyStoreType=JKS
server.ssl.key-store=
server.ssl.key-store-password=
server.ssl.key-alias=tomcat

server.ssl.client-auth=need
server.ssl.trust-store-type=JKS
server.ssl.trust-store=
server.ssl.trust-store-password=

11 SpringCloud openfeign服务调用

11.1 测试环境下,信任所有的证书

import feign.Client;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * @Description TODO.
 * @Author Nemo
 * @Date 2019/12/18/018 11:25
 * @Version 1.0

 * @Descirbe 参考https://blog.csdn.net/justry_deng/article/details/81042379

 * @Descirbe 参考https://www.jianshu.com/p/1b7288d050e3
 */
@Configuration
public class FeignHttpsConfig {

    @Bean
    @ConditionalOnMissingBean
    public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
                              SpringClientFactory clientFactory) throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext ctx = SSLContext.getInstance("SSL");
        X509TrustManager tm = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain,
                                           String authType) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain,
                                           String authType) throws CertificateException {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
        ctx.init(null, new TrustManager[]{tm}, null);
        return new LoadBalancerFeignClient(new Client.Default(ctx.getSocketFactory(),
                new HostnameVerifier() {
                    public boolean verify(String hostname, SSLSession sslSession) {
                        return true;
                    }
                }),
                cachingFactory, clientFactory);
    }
}

11.2 生产环境下,信任特定CA的证书

import feign.Client;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.*;
import java.io.*;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;



/**
 * @Description TODO.
 * @Author Nemo
 * @Date 2019/12/18/018 11:25
 * @Version 1.0

 * @Descirbe 参考https://blog.csdn.net/justry_deng/article/details/81042379

 * @Descirbe 参考https://www.jianshu.com/p/1b7288d050e3
 */
@Configuration
public class FeignHttpsConfig {

    @Bean
    @ConditionalOnMissingBean
    public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
                              SpringClientFactory clientFactory) throws NoSuchAlgorithmException, KeyManagementException, IOException, KeyStoreException {

        KeyStore keyStore = getKeyStore();

        TrustManagerFactory trustManagerFactory =
                TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);

        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
            throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
        }
        X509TrustManager x509TrustManager = (X509TrustManager) trustManagers[0];

        // 这里传TLS或SSL其实都可以的
        SSLContext ctx = SSLContext.getInstance("SSL");
        ctx.init(
                null,
                new TrustManager[]{x509TrustManager},
                new SecureRandom());

        return new LoadBalancerFeignClient(
                new Client.Default(
                        ctx.getSocketFactory(),
                        new HostnameVerifier() {
                            public boolean verify(String hostname, SSLSession sslSession) {
                                return true;
                            }
                        }),
                cachingFactory,
                clientFactory);
    }


    private KeyStore getKeyStore() throws IOException {

        // 使用证书中的所有信任的
        String caFile = "F:/work/workspace/nemo/nemo-study/nemo-study-xxl-job/ca/cacert.crt";
        InputStream caInputStream = null;
        // 如果是单向的,客户端一般是没有密码的
        // 如果是双向的,那么是需要密码的
        String caAlias = "";

        // 初始化KeyStore有三种方式,这里使用信任颁发者证书的方式
        // 证书工厂
        CertificateFactory certificateFactory = null;
        // 初始化秘钥仓库对象
        KeyStore keyStore = null;
        try {
            caInputStream = new FileInputStream(new File(caFile));
            certificateFactory = CertificateFactory.getInstance("X.509");
            keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            // 不用导入秘钥库,使用下面的信任的颁发者证书
            keyStore.load(null);
            keyStore.setCertificateEntry(
                    caAlias,
                    certificateFactory.generateCertificate(caInputStream));
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } finally {
            caInputStream.close();
        }

        return keyStore;
    }

}

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值