GeXiangDong

精通Java、SQL、Spring的拼写,擅长Linux、Windows的开关机

0%

制作HTTPS双向认证的网站

使用NGINX做双向认证的网站,访问时需要客户端安装有证书才可继续访问。可用于仅限特定用户群的网站,例如企业内部的业务管理系统,可提高系统安全性,阻止未授权用户访问。

在下述方法中,客户端证书采用自制(可节约成本),服务器端证书可自制也可购买,两者不必同一个CA,建议购买(有免费的域名证书)因为自制的浏览器会出现不信任标志。

自制证书使用openssl工具,使用前需要先安装.

制作证书

CA证书

1
2
3
4
5
#制作CA私钥
openssl genrsa -out ca.key 2048

#制作CA根证书(包含公钥),会要求填写信息
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt

服务器证书

如果使用购买的服务器证书,可忽略此部分

1
2
3
4
5
6
7
8
9
10
#制作服务器端私钥:
openssl genrsa -out server.key 2048
#服务器端公钥
openssl rsa -in server.key -out server.public.key

#生成CSR(证书签发请求)
openssl req -new -key server.public.key -out server.csr

#用CA私钥签发证书
openssl x509 -req -sha256 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -out server.crt

客户端浏览器证书

1
2
3
4
5
6
7
8
9
10
11
12
13
#制作客户端私钥
openssl genrsa -out client.key 2048
#客户端公钥
openssl rsa -in client.key -out client.public.key

#生成CSR(签发请求)
openssl req -new -key client.public.key -out client.csr

#用CA私钥签发证书
openssl x509 -req -sha256 -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 -out client.crt

#转成pfx格式
openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.pfx

生成CSR环节会要求输入一些信息,如下:

Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:SH
Locality Name (eg, city) []:SH
Organization Name (eg, company) [Internet Widgits Pty Ltd]:公司名(英文字母)
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:这里要输入你的主机名域名
Email Address []:someone@yourcompany.com

下面这段需要输入的两项保留为空(直接按回车)即可。

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

更改nginx配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server {
listen 443;
server_name admin.devmgr.cn;
ssl on;
# 服务器端证书配置,具体参数请根据证书发行方提供的帮助配置
ssl_certificate /etc/nginx/certs/1_admin.devmgr.cn_bundle.crt;
ssl_certificate_key /etc/nginx/certs/2_admin.devmgr.cn.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;

# 下面是配置客户端认证,需要配置使用的CA证书
ssl_client_certificate /etc/nginx/certs/ca.crt;
ssl_verify_client on;

root /var/www/admin;
}

在后端程序内获取客户端证书信息

NGINX会把客户端证书做成内置变量,可通过proxy_set_header传递给应用,在应用内获取request header即可得到证书对应的信息。

1
2
3
4
5
6
7
8
location /webapp {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 把客户端证书的主题信息作为request header (Client-Cert)传递给应用
proxy_set_header Client-Cert $ssl_client_s_dn;
}

除了 $ssl_client_s_dn 外,NGINX还提供很多内置变量对应证书的其他部分内容,想起请参考 nginx的ngx_http_ssl_module 模块文档。使用时需要注意nginx版本是否支持对应的变量。