签发CA证书:单向认证+双向认证
目录
开发前的环境准备:
客户端: win10+火狐浏览器/谷歌
服务端: COS7+Tomcat9
Tomcat9的文件路径: /usr/local/tomcat9
单向认证:
一、生成CA根证书
- 新建一个目录,用于存放证书
mkdir -p /srv/ftp/cas
- 生成CA密钥对:
openssl genrsa -out /srv/ftp/cas/cakey.pem 2048 RSA
- 生成根证书签发申请:
openssl req -new -key /srv/ftp/cas/cakey.pem -out /srv/ftp/cas/cacert.csr -subj /CN=cas.com
- 根证书签发:
openssl x509 -req -days 3650 -sha1 -extensions v3_ca -signkey /srv/ftp/cas/cakey.pem -in /srv/ftp/cas/cacert.csr -out /srv/ftp/cas/ca.cer
二、生成服务器的证书
- 新建一个目录,用于存放证书
mkdir -p /srv/ftp/cas/server
- 生成服务器私钥:
openssl genrsa -aes256 -out /srv/ftp/cas/server/server-key.pem 2048
设置密码:mldnjava
- 生成服务器证书签发申请:
openssl req -new -key /srv/ftp/cas/server/server-key.pem -out /srv/ftp/cas/server/server.csr -subj /CN=cas.com
- 服务端证书签发:
openssl x509 -req -days 3650 -sha1 -extensions v3_req -CA /srv/ftp/cas/ca.cer -CAkey /srv/ftp/cas/cakey.pem -CAserial /srv/ftp/cas/server/ca.srl -CAcreateserial -in /srv/ftp/cas/server/server.csr -out /srv/ftp/cas/server/server.cer
三、生成客户端的证书
- 新建一个目录,用于存放证书
mkdir -p /srv/ftp/cas/client
- 生成客户端私钥:
openssl genrsa -aes256 -out /srv/ftp/cas/client/client-key.pem 2048
设置密码:mldnjava
- 生成客户端证书签发申请:
openssl req -new -key /srv/ftp/cas/client/client-key.pem -out /srv/ftp/cas/client/client.csr -subj /CN=cas.com
- 客户端证书签发:
openssl x509 -req -days 365 -sha1 -CA /srv/ftp/cas/ca.cer -CAkey /srv/ftp/cas/cakey.pem -CAserial /srv/ftp/cas/server/ca.srl -in /srv/ftp/cas/client/client.csr -out /srv/ftp/cas/client/client.cer
四、转换为java可以使用的证书
- 生成客户端证书
openssl pkcs12 -export -clcerts -name cas-client -inkey /srv/ftp/cas/client/client-key.pem -in /srv/ftp/cas/client/client.cer -out /srv/ftp/cas/client/client.p12
- 生成服务器端证书:
openssl pkcs12 -export -clcerts -name cas-server -inkey /srv/ftp/cas/server/server-key.pem -in /srv/ftp/cas/server/server.cer -out /srv/ftp/cas/server/server.p12
设置密码:mldnjava
- 在本机系统中导入信任证书,随后会在"/usr/local/tomcat" 目录下生成"ca-trust.p12" 证书文件:
keytool -importcert -trustcacerts -alias cas.com -file /srv/ftp/cas/ca.cer -keystore /usr/local/tomcat/ca-trust.p12
- 使用keytool工具查看证书信息:
keytool -list -keystore /srv/ftp/cas/client/client.p12 -storetype pkcs12 -v
五、配置和启动tomcat
- 进入tomcat配置文件
/usr/local/tomcat9/conf/server.xml
<Connector port="443" protocol="HTTP/1.1" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" clientAuth="false" sslPortocol="TLS" keystoreFile="/srv/ftp/cas/server/server.p12" keystoreType="pkcs12" keystorePass="mldnjava" />
- 启动tomcat服务器:
/usr/local/tomcat9/bin/catalina.sh start
此时可以使用http请求访问,但并不支持https访问
1.3配置本地的hosts文件
C:\Windows\System32\drivers\etc\hosts
增加配置:10.200.1.87 cas.com
再次重启浏览器输入https://cas.com,成功访问!
双向认证:
- 停掉tomcat
/usr/local/tomcat9/bin/catalina.sh stop
- 配置tomcat server.xml,替换原来配置的单向认证的配置:
<Connector port="443" protocol="HTTP/1.1" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" clientAuth="true" sslPortocol="TLS" keystoreFile="/srv/ftp/cas/server/server.p12" keystoreType="pkcs12" keystorePass="mldnjava" truststoreFile="/usr/local/tomcat9/ca-trust.p12" truststoreType="jks" truststorePass="mldnjava" />
- 启动tomcat,此时再次访问https://cas.com,提示连接失败。需要在证书里面配置您的证书,把/usr/srv/ftp/cas/client/client.p12 这个证书下载下来导入到浏览器您的证书里,重启浏览器,输入https://cas.com,成功访问!
使用java模拟携带证书请求
- 根证书可以使用jdk的keytool工具安装,方式有很多种,这里只选用库文件的模式。
首先,把根证书ca.crt复制一份,重命名为ca.cer,然后把这个文件复制到jdk的jre\lib\security目录下,在这个目录中进行根证书的安装:
keytool -keystore test.truststore -keypass mldnjava -storepass mldnjava -alias DemoCA -import -trustcacerts -file ca.cer
其中,test.truststore可以自定义名称,密码自定义,DemoCA别名自定义,ca.cer即刚才复制过来的文件,最后需要输入一个y确认信任。
- java客户端代码:
package com.example.demo.Service;
import org.springframework.stereotype.Service;
import javax.net.ssl.*;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
@Service
public class SSLService {
/**
* 客户端证书路径
*/
private final static String CLIENT_CERT_FILE = "C:\\Users\\admin\\Desktop\\client.p12";
/**
* 客户端证书密码
*/
private final static String CLIENT_PWD = "mldnjava";
/**
* 信任库文件路径
*/
private final static String TRUST_STRORE_FILE = "C:\\Users\\admin\\Desktop\\test.truststore";
/**
* 信任库密码
*/
private final static String TRUST_STORE_PWD = "mldnjava";
private static String readResponseBody(InputStream inputStream) throws IOException {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
String buff = null;
while ((buff = br.readLine()) != null) {
sb.append(buff).append("\n");
}
return sb.toString();
} finally {
inputStream.close();
}
}
private static void httpsCall() throws Exception {
// 初始化密钥库
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance("SunX509");
KeyStore keyStore = getKeyStore(CLIENT_CERT_FILE, CLIENT_PWD, "PKCS12");
keyManagerFactory.init(keyStore, CLIENT_PWD.toCharArray());
// 初始化信任库
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance("SunX509");
KeyStore trustKeyStore = getKeyStore(TRUST_STRORE_FILE, TRUST_STORE_PWD, "JKS");
trustManagerFactory.init(trustKeyStore);
// 初始化SSL上下文
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory
.getTrustManagers(), null);
SSLSocketFactory sf = ctx.getSocketFactory();
HttpsURLConnection.setDefaultSSLSocketFactory(sf);
String url = "https://cas.com";
URL urlObj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) urlObj.openConnection();
con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 " +
"(KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36");
con.setRequestProperty("Accept-Language", "zh-CN;en-US,en;q=0.5");
con.setRequestMethod("GET");
String res = readResponseBody(con.getInputStream());
System.out.println(res);
}
/**
* 获得KeyStore
*/
private static KeyStore getKeyStore(String keyStorePath, String password, String type)
throws Exception {
FileInputStream is = new FileInputStream(keyStorePath);
KeyStore ks = KeyStore.getInstance(type);
ks.load(is, password.toCharArray());
is.close();
return ks;
}
public static void main(String[] args) throws Exception {
httpsCall();
}
}
- 执行代码,得到结果: