SSL tomcat

来源:互联网 发布:oa办公软件免费版 编辑:程序博客网 时间:2024/06/07 17:44

1.    配置Web服务器的SSL

本系统的Web服务运行在tomcat服务器上。配置服务器的SSL,需要为服务器申请证书,并进行一系列的设置。

(1)    生成服务器证书请求文件(CSR)

生成私钥和CSR文件需要使用keytool。Keytool.exe通常在%JAVA_HOME%/bin目录下。

使用以下命令生成keystore和keyEntry:

keytool –genkey –alias [keyEntry_name] –keyalg RSA –keystore [keystore_name]

genkey:产生密钥对。该证书链和私钥将储存于alias所标识的新密钥仓库中。

alias:密钥别名。

keyalg:用于生成密钥对的算法。

keystore:密钥仓库名称。

keytool会提示输入keystore的密码,您的名字与姓氏、单位、组织、城市、省份、国家。其中“您的名字与姓氏”要与网站的域名一致。

 使用以下命令生成CSR:

keytool –certreq –alias [keyEntry_name] –file request.crs –keystore [keystore_name]

certreq:生成PKCS#10格式的证书签名请求,即CSR。

输入keystore的密码,即可在本地目录中生成request.crs。

把此CRS文件发给CA,等待CA颁发证书。

 

(2)导入证书

CA根据CRS颁发证书后,需要把证书导入到keystore中。使用以下命令导入服务器证书:

keytool –import –trustcacerts –alias [keyEntry_name] –file certificate.txt –keystore [keysore_name]

import:向密钥库导入证书。

trustcacerts:指定该证书链为信任链。

file:证书或pkcs7证书链文件。

使用以下命令导入CA证书:

keytool –import –trustcacerts –alias [CA_name] –file certificate.txt –keystore [keysore_name]

 

(3)设置Tomcat的SSL连接

编辑Tomcat的配置文件使其支持SSL。在%TCAT_HOME%/conf目录下,使用XML编辑器打开server.xml,找到这一行:

<!—Define a SSL HTTP/1.1 Connector on port 8443-->

更改以下字段:

<!—

<connector port=”8443” protocol=”HTTP/1.1” SSLEnabled=”true”

maxThreads=”150” scheme=”https”

clientAuth=”false” sslProtocol=”TLS”/>

-->

    去掉两头的注释“<!--”和“-->”,使SSL配置生效。port=”8443”,代表SSL服务的端口。clientAuth=”false”表示不请求客户端证书,即单向认证。改为“true”则表示请求客户端证书,即双向认证。sslProtocol表示SSL连接的协议,这里使用TLS。同时在上述代码中添加keystoreFile文件、truststoreFile文件和crlFile文件的描述,其中crlFile是从CA下载的最新的被吊销的证书列表。完整的代码如下:

<connector port=”8443” protocol=”HTTP/1.1” SSLEnabled=”true”

maxThreads=”150”  scheme=”https”  

clientAuth=”true/flase” sslProtocol=”TLS”

keystoreFile=” test.keystore文件的路径”

keystorePass=”test.keystore文件的密码”

truststoreFile=” test.keystore文件的路径”

truststorePass=” test.keystore文件的密码”

crlFile="certcrl.crl文件的路径"/>

完成以上设置之后,重新启动Tomcat。

 

2.基于SSL双向认证的登录服务的实现

若服务器配置为双向认证(即在上述代码中设置clientAuth=”true”),当用户以所设定的端口访问该服务器时,浏览器将跳出一个对话框让用户选择要提交进行认证的证书,供选择的只有该服务器信任的CA颁发的证书。

如前所述,应用层只需要获得用户证书,查询数据库,验证证书序列号即可。

需要引入的包有: “java.security.cert”,“jdbc”。前者包含的主要类有“X509Certificate”,“X509CRL”,“CertificateFactory”;后者包含所有有关数据库操作的自编程序,其中主要的类有“DbOperation”,“UserInfo”。

核心代码如下:

X509Certificate[]ca=(X509Certificate[])request.getAttribute("javax.servlet.request.X509Certificate");//获取证书链

X509Certificate x509certificate=ca[0];//获得用户证书

String StrSerialNumber;

StrSerialNumber=x509certificate.getSerialNumber().toString();//得到证书序列号

DbOperation dbOperation = new DbOperation();

UserInfo user = dbOperation.getUserInfoByname(Strname);//查询数据库,得到用户记录

if(StrSerialNumber.equals(user.getUserserial()))

    {

    user_IsValid="true";

}//验证证书序列号

 

3. 基于SSL单向认证的登录服务的实现

若服务器配置为单向认证(即设置clientAuth=”false”),当用户以所设定的端口访问该服务器时,浏览器不会自动跳出对话框让用户选择要提交进行认证的证书。为了得到证书我们需要一个控件。

在此ActiveX控件中添加了三个方法:

BSTR GetUserList();//获得证书列表

BSTR GetUserCert(BSTR sUserName);//根据证书名称获得对应证书(Base64编码)

BSTR SignData(BSTR sUserName,BSTR sDataToSign);//根据证书名称对数据签名,返回Base64编码的签名数据

用脚本调用该控件获得用户证书以及用户对随机数的签名文件,然后应用层对证书进行认证。

需要引入的包有: “java.security.cert”,“jdbc”,“java.security”。“java.security”中主要类有“Signature”。

验证用户证书的核心代码如下:

//检验证书有效期

try{

oCert.checkValidity();

}catch(Exception e){

       e.printStackTrace();

       request.setAttribute("ErrMsg", "没有提供有效的数字证书。");

      request.getRequestDispatcher("err.jsp").forward(request, response);

        return;

}

 

//检验签发用户证书的CA是否被信任

String issuer=oCert.getIssuerDN().toString();

if(issuer.equals("CN=TestCA"));

 else verify=false;

 

//检验证书是否被CA吊销

InputStream inStream = new FileInputStream("D:/Program Files/jre/bin/certcrl.crl");

 CertificateFactory cf = CertificateFactory.getInstance("X.509");

 X509CRL crl = (X509CRL)cf.generateCRL(inStream);

 inStream.close();

 if(crl.isRevoked(oCert))

 verify=false;

 

//查询数据库,验证证书序列号

 DbOperation dbOperation = new DbOperation();

UserInfo user = dbOperation.getUserInfoByname(clientname);

if(user.getUserserial().equals(strSerialNumber));

else verify=false;

 

//验证随机数签名

Signature oSign = Signature.getInstance("SHA1withRSA");

oSign.initVerify(oCert);          

signedBuf = oDecoder.decodeBuffer(UserSignedData);

oSign.update(rand.getBytes());

verify = oSign.verify(signedBuf);