参考文章:
https://blog.csdn.net/xiangguiwang/article/details/76400805
https://blog.csdn.net/qq_37049781/article/details/84837342
一、首先 证书的概念。
X.509证书,其核心是根据RFC 5280编码或数字签名的数字文档。
X.509 DER 编码(ASCII)的后缀是: .DER .CER .CRT
X.509 PAM 编码(Base64)的后缀是: .PEM .CER .CRT
nginx配置和springboot配置还是有区别的,这里坑很多。我的环境是windows+springboot+nginx。双向.认证配置springboot需要的是服务器证书库serve.jks和客户端证书 server.crt。而nginx需要的是服务器证书 server.pem,服务器秘钥privateKey.key,以及客户端证书client.pem(这里要根据linux需要的证书格式给)。
二、配置nginx
upstream tomcatsever{
server 192.168.43.238:8080;#代理服务器及端口
}
server {
listen 8089; #nginx监听端口
server_name 192.168.43.238:8089;
#charset koi8-r;
#access_log logs/host.access.log main;
listen 443 ssl; #打开ssl认证
ssl_certificate G:\work\jks\project\server.pem; #服务器证书
ssl_certificate_key G:\work\jks\project\privateKey.key; #服务器私钥
ssl_client_certificate G:\work\jks\project\client.pem;#客户端证书
ssl_verify_client on; #打开客户端认证
location / {
root html;
index index.html index.htm;
proxy_pass http://tomcatsever;
}
location /api/ {
proxy_pass http://tomcatsever;
}
1.upstream后面的tomcatsever 不要加下划线,tomcat从7.0以后不支持了,不然会报错。
2.如果改了端口,原来的配置端口还可以访问,新的配置无效,要手动杀死nginx.exe程序,重新启动。
3.要想局域网可用,设置listen后面的端口A,servername要设成 ip+A。注意防火墙关闭
4.证书的格式需要 pem还是der,根据nginx配置。
三、证书格式转化(pem转 der,der转pem)
linux环境一般自带 openssl,windows环境还需要安装
PEM到DER
openssl x509 -in cert.crt -outform der-out cert.der
DER到PEM
openssl x509 -in cert.crt -inform der -outform pem -out cert.pem
四、 查看 pem、der格式证书信息
1.查看pem格式
openssl x509 -in cert.pem -text -noout
2.查看der格式
openssl x509 -in certificate.der -inform der -text -noout
五、提取私钥
这里有两种办法,一是openssl,二是java代码
第一种:
jks先转 pfx格式
keytool -v -importkeystore -srckeystore server.jks -srcstoretype jks -srcstorepass demopwd -destkeystore server.pfx -deststoretype pkcs12 -deststorepass password-destkeypass password
pfx 转pem格式
openssl pkcs12 -in server.pfx -nodes -out server.pem
提取公钥:
openssl rsa -in server.pem -out pub.key
提取私钥:
openssl x509 -in server.pem -out pri.key
第二种:
/**
* @author zhen
* @Date 2018/4/16 10:58
*/
public class ExportCert {
//导出证书 base64格式
public static void exportCert(KeyStore keyStore, String alias, String exportFile) throws Exception {
Certificate certificate = keyStore.getCertificate(alias);
BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(certificate.getEncoded());
FileWriter fw = new FileWriter(exportFile);
fw.write("------BEGIN CERTIFICATE----- \r\n ");//非必须
fw.write(encoded);
fw.write("\r\n-----END CERTIFICATE-----");//非必须
fw.close();
}
//得到KeyPair
public static KeyPair getKeyPair(KeyStore keyStore, String alias, char[] password){
try{
Key key = keyStore.getKey(alias, password);
if (key instanceof PrivateKey){
Certificate certificate = keyStore.getCertificate(alias);
PublicKey publicKey = certificate.getPublicKey();
return new KeyPair(publicKey, (PrivateKey) key);
}
}catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException e){
e.printStackTrace();
}
return null;
}
//导出私钥
public static void exportPrivateKey(PrivateKey privateKey, String exportFile) throws Exception {
BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(privateKey.getEncoded());
FileWriter fileWriter = new FileWriter(exportFile);
fileWriter.write("-----BEGIN PRIVATE KEY-----\r\n");//非必须
fileWriter.write(encoded);
fileWriter.write("\r\n-----END PRIVATE KEY-----");//非必须
fileWriter.close();
}
//导出公钥
public static void exportPublicKey(PublicKey publicKey, String exportFile) throws Exception {
BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(publicKey.getEncoded());
FileWriter fileWriter = new FileWriter(exportFile);
fileWriter.write("-----BEGIN PUBLIC KEY-----\r\n");//非必须
fileWriter.write(encoded);
fileWriter.write("\r\n-----END PUBLIC KEY-----");//非必须
fileWriter.close();
}
public static void main(String[] args) throws Exception{
String keyStoreType = "jks";
String keystoreFile = "G:\\work\\jks\\project\\server.key.p12";
String password = ""; //keystore的解析密码
String friendPassword = "";//条目的解析密码
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(new FileInputStream(keystoreFile), password.toCharArray());
String alias = "server";//条目别名
String exportCertFile = "G:\\work\\jks\\project\\cert.crt";
String exportPrivateFile = "G:\\work\\jks\\project\\privateKey.key";
String exportPublicFile = "G:\\work\\jks\\project\\publicKey.key";
ExportCert.exportCert(keyStore, alias, exportCertFile);
KeyPair keyPair = ExportCert.getKeyPair(keyStore, alias, friendPassword.toCharArray()); //注意这里的密码是你的别名对应的密码,不指定的话就是你的keystore的解析密码
ExportCert.exportPrivateKey(keyPair.getPrivate(), exportPrivateFile);
ExportCert.exportPublicKey(keyPair.getPublic(), exportPublicFile);
System.out.println("OK");
}
这样 nginx https双向认证配置就完成了。