自签名证书实现 java服务 <->nginx HTTPS 双向认证

本文详细介绍了如何生成自签名的SSL证书,并在Java和Nginx环境中进行配置。首先,利用OpenSSL命令创建了根证书和客户端/服务器证书,接着在Nginx配置中启用SSL,设置证书验证。然后,展示了Java中如何加载和验证SSL证书,最后提到了证书导入浏览器和Maven处理证书的注意事项。
摘要由CSDN通过智能技术生成

生成证书

C="CN"
ST="Zhejiang"
L="HanZhou"
O="Alibaba"
OU="Nginx"
CN="11.22.33.44"
CN_CLIENT="MicroService"
emailAddress="abc@edf.com"
PASSWD="password"
JKS_PASSWD="password"

rm -rf temp
mkdir temp
cd temp/
mkdir -p demoCA/newcerts
touch demoCA/index.txt
touch demoCA/serial
echo 01 >> demoCA/serial

# 生成自签名根证书 ca key 
openssl genrsa -aes128 -passout pass:${PASSWD} -out ca.key 2048
# ca crt(pem) der
openssl req -new -passin pass:${PASSWD}  -x509 -key ca.key -out ca.crt -days 3650 -subj "/C=${C}/ST=${ST}/L=${L}/O=${O}/OU=${OU}/CN=${CN}/emailAddress=${emailAddress}"
openssl x509 -in ca.crt -outform DER -out ca.der
openssl x509 -inform der -in ca.der -out ca.pem

# server key
# openssl genrsa -aes128 -passout pass:${PASSWD} -out serverKey.pem 2048
openssl genrsa -out serverx.key 2048
# server req
#openssl req -new -passin pass:${PASSWD}  -key serverKey.pem -out serverReq.pem -subj  "/C=${C}/ST=${ST}/L=${L}/O=${O}/OU=${OU}/CN=${CN}/emailAddress=${emailAddress}"
openssl req -new -key serverx.key -out serverReq.pem -subj  "/C=${C}/ST=${ST}/L=${L}/O=${O}/OU=${OU}/CN=${CN}/emailAddress=${emailAddress}"
# server cert
openssl ca -md sha256 -key ${PASSWD} -batch -keyfile ca.key -cert ca.crt -in serverReq.pem -out serverCrt.pem -days 3650
rm serverReq.pem 

# client key
openssl genrsa -aes128 -passout pass:${PASSWD} -out clientKey.pem 2048
# client req
openssl req -new -passin pass:${PASSWD}  -key clientKey.pem -out clientReq.pem -subj  "/C=${C}/ST=${ST}/L=${L}/O=${O}/OU=${OU}/CN=${CN_CLIENT}/emailAddress=${emailAddress}"
# client cert
openssl ca -md sha256 -key ${PASSWD} -batch -keyfile ca.key -cert ca.crt -in clientReq.pem -out clientCert.pem -days 3650
rm clientReq.pem 

# 所有证书,私钥等都可以是 pem, 也可以是 der 格式, 可以转化
# openssl x509 -in ca.crt -outform DER -out ca.der  # pem -> der
# openssl x509 -inform der -in ca.der -out ca.pem   # der -> pem

# 假如要取消某个证书openssl
# openssl ca -keyfile ca.key -cert ca.crt -revoke clientCert.pem

# jks
# keyStore for client 客户端会给自己的公钥证书给服务端,服务端判断这个证书是不是自己的信任链上的
openssl pkcs12 -export -out slb_sslclient.p12 -in clientCert.pem -inkey clientKey.pem
keytool -importkeystore -srckeystore slb_sslclient.p12 -srcstoretype PKCS12 -deststoretype  JKS -destkeystore keystore.jks

# trustStore for client 服务端给自己的公钥证书给客户端,客户端判断这个证书是不是自己的信用链上的
keytool -import -trustcacerts -file ca.crt -keystore truststore.jks -storepass ${JKS_PASSWD}

nginx配置

	# HTTPS server
    #
    server {
		listen       8443 ssl;
        server_name  localhost;

        ssl_certificate     ./nginx/conf/ssl/servercrt.pem;
        ssl_certificate_key   ./nginx/conf/ssl/servercrt.key;
		ssl_client_certificate  ./nginx/conf/ssl/ca.crt;
		ssl_verify_client on;

		ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256";
		ssl_prefer_server_ciphers on;
		ssl_session_cache shared:SSL:10m; 
		ssl_session_timeout 10m;

		ssl_protocols  TLSv1.2;
        location /  {
            # 校验证书DN,防止根证书的其他证书也通过认证
            if ($ssl_client_s_dn !~ "CN=xxx,OU=xxx,O=xxx,C=CN") {
                return 403;
            }
			proxy_pass https//elasticsearch;
        } 
    }
	
	upstream elasticsearch  {
        server 11.22.33.44:9200;
    }
	
	

java配置


        try {
            String keystorePassPlain = PwdUtils.decryptSecretInfo(keystorePass);
            KeyStore keyStore = KeyStore.getInstance("jks");
            kis = new FileInputStream(new File(
                PathUtil.getAbsolutePath(keystorePath).orElse(StringUtils.EMPTY) + File.separator + "keystore.jks"));
            keyStore.load(kis, keystorePassPlain.toCharArray());

            String truststorePassPlain = PwdUtils.decryptSecretInfo(truststorePass);
            KeyStore trustStore = KeyStore.getInstance("jks");
            tis = new FileInputStream(new File(
                PathUtil.getAbsolutePath(keystorePath).orElse(StringUtils.EMPTY) + File.separator + "truststore.jks"));
            trustStore.load(tis, truststorePassPlain.toCharArray());

            SSLContextBuilder sslbuild = SSLContexts.custom().loadTrustMaterial(trustStore, (x509Certificates, s) -> {
                for (X509Certificate x509Certificate : x509Certificates) {
                    x509Certificate.checkValidity();
                }
                return false;
            }).loadKeyMaterial(keyStore, keystorePassPlain.toCharArray()).useProtocol("TLSv1.2");


            SSLContext sslcontext = sslbuild.build();
            this.builder.setHttpClientConfigCallback((httpClientBuilder) -> {
                return httpClientBuilder.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                    .setSSLContext(sslcontext);
            });
        } catch (Exception var13) {
            LOG.error("setSSLContext failed.", var13);
        } finally {
            try {
                if (tis != null) {
                    tis.close();
                }
                if (kis != null) {
                    kis.close();
                }
            } catch (IOException e) {
                tis = null;
                kis = null;
                LOG.error("close fileInputStreams error: ", e);
            }
        }

p12证书导入证书到浏览器

根证书,放入 受信任的根证书颁发机构

P12证书包含了客户端私钥和证书,等价于keystore.jks,放入个人

如果使用根证书+中间证书,需要在trustStore中添加整个信用链(包括根证书+中间证书),nginx 上前后复制粘贴放在一个文件里面就行

vi /etc/hosts

Maven有可能会把证书文件做编码处理,加上这个可以避免

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值