一.首先我们需要生成服务器端和客户端的数字证书并添加信任
实际应用环境里,需要向CA机构申请服务器证书。这里我们为了测试方便通过Keytool工具生成自签名证书来模拟。
注:相关参数说明请使用 keytool -help 查阅
1. 生成服务器端证书
keytool -genkey -v -keyalg RSA -keysize 1024 -sigalg SHA1withRSA -validity 36000 -alias www.alan.org -keystore alan.keystore -keystore alan.keystore -dname “CN=www.alan.org,OU=alan,O=alan,L=HN,ST=HN,C=CN”
2. 生成客户端证书
keytool -genkey -v -keyalg RSA -keysize 1024 -sigalg SHA1withRSA -validity 36000 -alias alanClient -storetype PKCS12 -keystore alanClient.p12 -dname “CN=alan-client,OU=alan,O=alan,L=HN,ST=HN,C=CN”
3. 让服务器信任客户端证书
(1)从刚刚生成的客户端证书库中导出客户端证书
keytool -export -alias alanClient -keystore alanClient.p12 -storetype PKCS12 -rfc -file alanClient.cer
(2) 导入客户端证书到服务器证书库作为一个信任证书
keytool -import -v -file alanClient.cer -keystore alan.keystore
4. 导入客户端证书到IE证书库
双击执行alanClient.p12文件导入证书到“个人”证书库。
注:实际应用中,客户端如果使用电子钥匙,则使用相应电子钥匙驱动工具注册钥匙内数字证书到IE证书库即可
二. 配置WEB服务器端(以Tomcat服务器为例)
在Tomcat的server.xml文件中配置双向认证,配置代码参考如下:
<Connector
port="443"
protocol="HTTP/1.1"
SSLEnabled="true"
maxThreads="150"
scheme="https"
secure="true"
clientAuth="true"
sslProtocol="TLS"
keystoreFile="conf/alan.keystore"
keystorePass="changeit"
truststoreFile="conf/alan.keystore"
truststorePass="changeit"/>
注:如果这里密钥库文件使用PKCS12格式,则还需指定keystoreType="PKCS12"
三.服务器端代码参考(以Java为例)
添加一个过滤器,过滤请求并获取属性“javax.servlet.request.X509Certificate”的值:
import java.io.IOException;import java.security.cert.CertificateExpiredException;import java.security.cert.CertificateNotYetValidException;import java.security.cert.X509Certificate; import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.annotation.WebFilter; /** * CertFilter */@WebFilter(description = "Certificate Filter for SSL connection", urlPatterns = { "/CertFilter" })public class CertFilter implements Filter { /** * Default constructor. */ public CertFilter() { // TODO Auto-generated constructor stub } /** * @see Filter#destroy() */ public void destroy() { // TODO Auto-generated method stub } /** * 获取证书信息 */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 获取request参数“javax.servlet.request.X509Certificate”中的证书信息 X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate"); for(X509Certificate cert : certs) { System.out.println("!!!Start!!!"); System.out.println("版本:" + cert.getVersion()); System.out.println("序列号:" + cert.getSerialNumber()); System.out.println("颁布者:" + cert.getIssuerDN().getName()); System.out.println("使用者(主题项):" + cert.getSubjectDN().getName()); System.out.println("签名算法:" + cert.getSigAlgName()); System.out.println("证书类型:" + cert.getType()); System.out.println("有效期从:" + cert.getNotBefore()); System.out.println("至:" + cert.getNotAfter()); try { cert.checkValidity(); // 检查证书是否过期 } catch (CertificateExpiredException e) { e.printStackTrace(); } catch (CertificateNotYetValidException e) { e.printStackTrace(); } System.out.println("!!!End!!!"); } // pass the request along the filter chain chain.doFilter(request, response); } /** * @see Filter#init(FilterConfig) */ public void init(FilterConfig fConfig) throws ServletException { // TODO Auto-generated method stub } }
四.客户端通过HTTPS访问服务器
因为是自签名证书,所以这里会有提示,点击“继续浏览此网站”即可进入,同时在后台可以看到如下打印输出:
因为是自签名证书,所以这里会有提示,点击“继续浏览此网站”即可进入,同时在后台可以看到如下打印输出:
至此,SSL/TLS双向认证即配置成功!可以根据自己的业务需求对获取到的证书信息进行相关业务操作即可。