关于JAVA与nginx双向认证的总结

目录

一、 研究目的和简要
二、 Openssl生成级联证书
三、 Nginx配置双向认证
四、 Java实现双向认证
五、 证书关系图

一、 研究目的和简要

看着简单的SSL证书,可以说绝对被SSL证书的外表欺骗了。为什么写这么多?我也很讨厌要看一大堆东西才实现的功能!但SSL双向认证真需要这么多字来说明(虽然废话也挺多,例如这句)。笔者研究了1个星期,最终是实现了双向认证,但对ssl认证过程和加密过程还是没有完全明白。网上是有很多关于生成证书和java代码实例,但大多都不能在实际工程场景中发挥作用。内容是挺多的,请耐心看,虽然理解方面存在我的脑洞,但可以保证这个文章绝对不是从网上简单的复制粘贴,是真材实料,杠杠的研究。
目的:
熟悉https请求双向认证的原理和运用方法,并在实际环境中得到正确使用
简要:
由于程序研究过程以及网络培训视频、网络文章等多以自己生成非正规CA发布的证书,绝大部分生成的证书与实际服务器使用的证书差别较大,在笔者生成大量证书(其实也就10套左右)后,感谢地址
https://blog.csdn.net/langeldep/article/details/54675898?utm_source=blogxgwz8
生成的证书经笔者测试可实现双向验证。
测试包括(细节将在“Nginx配置双向认证”和“Java实现双向认证”中体现):同一套证书验证可通过验证,客户端不信任或者信任另一套证书不可通过验证等。
证书生成后,nginx需要正确配置和Java代码正确配置才可达到双向认证成功的效果。Nginx配置错误或者无效,多出现无论以什么证书,只要有证书就可通过验证的情况。在nginx配置正确后,这时Java代码只要没有正确配置就会出现验证失败。
以上是关于“Openssl生成级联证书”、“Nginx配置双向认证”、“Java实现双向认证”等小节之必要的说明。

二、 Openssl生成级联证书

参考来源: https://blog.csdn.net/langeldep/article/details/54675898?utm_source=blogxgwz8
以下所有步骤都是在root用户下执行。

第一步:生成相关目录和文件

笔者使用的是linux虚拟机研究,openssl安装后与参考网站的一样,配置文件在/etc/pki/tls,所以跟着作了:

mkdir /etc/pki/ca_linvo
cd /etc/pki/ca_linvo
mkdir root server client newcerts
echo 01 > serial
echo 01 > crlnumber
touch index.txt

经过思考,生成这些文件可能是为了区分原文件夹,避免证书管理混乱。而笔者在生成第二套证书时,发现用原来的文件夹保存第二套也是有问题的,这涉及到第二步为什么要修改openssl配置文件。所以还是乖乖生成这些文件夹和文件,每新建一套都创建一个。

第二步:修改openssl配置

修改配置之前,笔者担忧出错,所以拷贝了一份配置文件的备份,参考操作为:

cp /etc/pki/tls/openssl.cnf /etc/pki/tls/openssl.cnf_bak
vi /etc/pki/tls/openssl.cnf

说明一下,上面的openssl.cnf就是openssl的配置文件
[ ca ]下的default_ca改为自己的ca名字,例如参考网站中的[ CA_linvo ]
操作方式:注释掉原来的,添加自己的
openssl配置文件的ca指定配置
复制ca设置并改成自己的。原设置是[ CA_default ],赋值一遍粘贴一下就可以了
红色框框是拷贝openssl配置文件内容
将自己复制的那一份设置中的下面三个参数改为对应参数,具体的参数根据创建的文件夹而定:

dir = /etc/pki/ca_linvo
certificate = $dir/root/ca.crt
private_key = $dir/root/ca.key

如果只是创建一套,可以忽略这一段话→→→这里certificatec和private_key的参数说明了根证书只能是ca.crt,根私钥只能是ca.key,所以笔者在创建第二套级联证书的根证书时,想到要去修改配置文件怕会造成证书管理混乱,所以在生成第二套时,又创建了一个证书文件夹ca_lan并在配置文件中加入了另一个CA_lan的设置,这样两套证书就分开管理了。
修改完后,shift+ZZ或者:wq保存修改
(tips: vi或者vim在按入i键后进入编辑模式,编辑模式中按Esc退出编辑模式,在这种情况下使用shift+ZZ或者:wq才是退出并保存修改)

第三步:创建根证书

创建根证书私钥:

openssl genrsa -des3 -out /etc/pki/ca_linvo/root/ca.key 2048

创建根证书请求文件:

openssl req -new -key /etc/pki/ca_linvo/root/ca.key -out /etc/pki/ca_linvo/root/ca.csr

创建根证书:

openssl x509 -req -days 3650 -in /etc/pki/ca_linvo/root/ca.csr -signkey /etc/pki/ca_linvo/root/ca.key -out /etc/pki/ca_linvo/root/ca.crt

创建证书吊销列表:

openssl ca -gencrl -out /etc/pki/ca_linvo/root/ca.crl -crldays 7

需要注意这里的路径需要改为自己创建的文件夹路径,例如笔者创建第二套证书时,创建秘钥是使用:openssl genrsa -des3 -out /etc/pki/ca_lan/root/ca.key 2048,不同点是-out后面的路径不同。
ca.key为私钥,csr是请求文件,crt是证书,crl证书吊销列表。
笔者理解如下:
作者自己画的图
最终目的是得到crt证书。形象地讲,有了私钥是一种身份证明,就像我是有钥匙的人了,我用这个钥匙可以去锁东西了,想打开我锁的东西,那就请得到我允许打开的证明(crt证书),证书怎么来?把我承认的请求(csr)发给我,我就给你证书。这个想象式理解只是笔者自己的脑洞,可能跟实际作用有出入。
可以说笔者并没有深入研究,这里大部分是笔者脑洞,包括所有小节。

第四步:生成服务器证书

生成服务器证书私钥:

openssl genrsa -des3 -out /etc/pki/ca_linvo/server/server.key 2048

生成服务器证书请求文件:

openssl req -new -key /etc/pki/ca_linvo/server/server.key -out /etc/pki/ca_linvo/server/server.csr

生成服务器证书:

openssl ca -in /etc/pki/ca_linvo/server/server.csr -cert /etc/pki/ca_linvo/root/ca.crt -keyfile /etc/pki/ca_linvo/root/ca.key -out /etc/pki/ca_linvo/server/server.crt -days 3650

同样要注意修改一下路径未自己创建的文件夹路径。
在这里插入图片描述
同样脑洞开始:证书比根证书多了一个根证书的签名。就像这个证书虽然是一个私钥生成的,但这个有证书还被那个人的老板签了个字,这样它老板可以解释这个证书是不是被认可的。客户端拿着这个证书用根证书验证就可以通过。

第五步:生成客户端证书

生成客户端证书私钥:

openssl genrsa -des3 -out /etc/pki/ca_linvo/client/client.key 2048

生成客户端证书请求文件:

openssl req -new -key /etc/pki/ca_linvo/client/client.key -out /etc/pki/ca_linvo/client/client.csr

生成客户端证书:

openssl ca -in /etc/pki/ca_linvo/client/client.csr -cert /etc/pki/ca_linvo/root/ca.crt -keyfile /etc/pki/ca_linvo/root/ca.key -out /etc/pki/ca_linvo/client/client.crt -days 3650

同样要注意修改一下路径未自己创建的文件夹路径。
方式跟第四步服务器证书生成一样。参考网站中提到服务器似乎不用根证书参与,所以有以下脑洞:
在这里插入图片描述
浏览器访问会从服务器中获取服务器证书,所以浏览器只添加客户端证书就可以。
Tips:其它有帮助的命令,以下命令自己注意一下路径和文件名
生成客户端证书安装pfx文件,双击就可安装到电脑中,浏览器就可识别:

openssl pkcs12 -export -inkey /etc/pki/ca_linvo/client/client.key -in /etc/pki/ca_linvo/client/client.crt -out /etc/pki/ca_linvo/client/client.pfx

生成java可用的p12文件:

openssl pkcs12 -export -clcerts -in client-cert.cer -inkey client-key.key -out client.p12

秘钥转非秘秘钥:可以用来转服务器证书,转了非秘秘钥后,nginx重启就不用输入秘钥密码

openssl rsa -in danfeng.key -out danfeng_nopass.key

三、 Nginx配置双向认证

以下内容在nginx配置文件中设置,在主体中设置。

server{
}

其它设置自行去学习,这里只列出配置部分的设置

server{


ssl on;
ssl_certificate /xxxxxxxxxxxxxx/ssl/myssl/server.crt;
ssl_certificate_key /xxxxxxxxxxxxxx/ssl/myssl/server_nopass.key;
ssl_client_certificate /xxxxxxxxxxxxxx/ssl/myssl/ca.crt;
ssl_verify_depth 2;
ssl_verify_client on;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;

}

主要由以下几个参数需要理解:
ssl on : 设置启动https请求
ssl_certificate :设置服务器证书
ssl_certificate_key :设置服务器证书秘钥
ssl_client_certificate :设置根证书,用于验证客户端
ssl_verify_depth :设置验证程度
ssl_verify_client :设置是否开启客户端验证
其它的为什么不写出来?因为我也没有去详细研究

测试过程:
客户端带证书访问可正常访问
客户端不带证书不可访问
注释掉ssl_verify_client那一行,不管有没有客户端证书都可以访问,并且同时注释掉ca证书那一行也一样,而待客户端证书访问的响应数据也是正常。这里怀疑客户端发送内容是不是没有加密?

四、 Java实现双向认证

java需要一个信任服务器证书和客户端证书,下面用两种方式处理证书和信任库(应该针对不同的证书有不同的方式)。

第一种方式:使用httpclient处理:

java代码:参考来源:https://www.cnblogs.com/dreamingodd/p/7491098.html

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
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.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;


/**
 * #1
 * HTTPS 双向认证 - direct into cacerts
 * @Author Ye_Wenda
 * @Date 7/11/2017
 */
public class HttpsDemo {
   
    // 客户端证书路径,用了本地绝对路径,需要修改
    private final static String TRUST_PATH = "F:\\自己生成的证书\\openssl证书\\级联证书\\ca_linvo\\server\\tserver.keystore";
    private final static String PFX_PATH = "F:\\自己生成的证书\\openssl证书\\级联证书\\ca_linvo\\client\\client.p12";
    private final static String PFX_PWD = "333333"; //客户端证书密码及密钥库密码

    public static String sslRequestGet(String url) throws Exception {
   
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        InputStream instream = new FileInputStream(new File(PFX_PATH));
        try {
   
            // 这里就指的是KeyStore库的密码
            keyStore.load(instream, PFX_PWD.toCharArray());
        } finally {
   
            instream.close();
        }

        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, PFX_PWD.toCharArray()).build();
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext
                , new String[] {
    "TLSv1" }  // supportedProtocols ,这里可以按需要设置
                , null  // supportedCipherSuites
                , SSLConnectionSocketFactory.getDefaultHostnameVerifier());

        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        try {
   
//            HttpGet httpget = new HttpGet(url);
            HttpPost httpget = new HttpPost(url);
//          httpost.addHeader("Connection", "keep-alive");// 设置一些heander等
            CloseableHttpResponse response = httpclient.execute(httpget);
            try {
   
                HttpEntity entity = response.getEntity
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Nginx支持双向认证,也称为客户端证书认证。在双向认证中,客户端和服务器之间都需要相互验证身份。下面是实现Nginx双向认证的一般步骤: 1. 生成服务器证书和私钥:首先需要生成服务器的证书和私钥。可以使用OpenSSL命令来生成自签名证书或者通过证书机构获得有效的证书。 2. 配置Nginx服务器:在Nginx的配置文件中,需要指定服务器证书和私钥的路径,并启用SSL/TLS。以下是一个简单示例: ``` server { listen 443 ssl; server_name example.com; ssl_certificate /path/to/server.crt; ssl_certificate_key /path/to/server.key; # 其他配置项 } ``` 3. 生成客户端证书和私钥:为每个客户端生成唯一的证书和私钥。可以使用相同的方法来生成自签名证书或者通过证书机构获得有效的证书。 4. 配置客户端验证:在Nginx的配置文件中,需要配置客户端验证参数。以下是一个示例: ``` server { listen 443 ssl; server_name example.com; ssl_certificate /path/to/server.crt; ssl_certificate_key /path/to/server.key; ssl_client_certificate /path/to/ca.crt; ssl_verify_client on; # 其他配置项 } ``` 在上述示例中,`ssl_client_certificate`指定了CA证书,`ssl_verify_client on`启用了客户端验证。 5. 配置访问控制:如果需要对特定的客户端进行访问控制,可以在配置文件中添加相应的访问限制。 6. 重启Nginx服务器:完成以上步骤后,重新加载或重启Nginx服务器,使配置生效。 通过以上步骤,Nginx将会进行双向认证,客户端和服务器将相互验证身份。需要注意的是,双向认证涉及到证书和私钥的生成、配置和管理,因此需要谨慎操作,并确保证书的安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值