實現在 Linux 下 Tomcat 的雙向SSL認證 轉帖(http://www.cnblogs.com/bjrmt/archive/2006/08/01/464634.html)

來源:互聯網
上載者:User

一、前言:

  關於如何使用Tomcat伺服器實現雙向SSL認證的文章很早就有了, 比較實用的文章可以看看 IBM developerWorks 中國網站 2002年5月 配置Tomcat 4使用雙向SSL( http://www-900.ibm.com/developerWorks/cn/security/se-tcssl/index.shtml )以及 配置Tomcat 5使用雙向SSL (http://thinkbase.net/w/main/Wiki?Tomcat5SSL_ServerAndClient)。

      關於原理方面不是本文的重點,故下面只講解實際操作的過程以及每個過程的說明:

二、需要的軟體包:

       Tomcat 5.0.25
       用途:Web Server。
      下載: http://jakarta.apache.org/builds/jakarta-tomcat-5.0/release/v5.0.25/bin/

       JSSE 1.0,2
       用途:用來產生Tocmcat使用的秘鑰對(keystore)。 在 JDK 1.4以上版本 中已經內建了這個工具, 因此, 只需要安裝 JDK1.4.x 即可
       下載: http://java.sun.com/products/jsse/

       Openssl 0.9.9.6
       用途:用來產生CA認證、簽名並產生IE可匯入的PKCS#12格式私密金鑰。
       下載: http://www.openssl.org/

       以上工具的安裝過程可以參考內建的協助,本文就不再詳細描述了。

三、認證環境設定:

export CA_DN=/C=CN/ST=GuangDong/L=GuangZhou/O=boss ssl/OU=Boss CACenter/CN=Boss CA Root/emailAddress=winsonhrh@gmail.com

export SERVER_DNAME=CN=21cn.com,OU=Boss Server,O=boss ssl,L=GuangZhou,ST=GuangDong,C=CN
export SERVER_KEYPASS=openssl
export SERVER_STOREPASS=openssl
export SERVER_ALIAS=boss-alias
export SERVER_KEYSTORE=boss-alias.keystore

export CLIENT_DN_OU=W21cn-boss-client
export CLIENT_DN_CN=Huronghua
export CLIENT_DN=/C=CN/O=W21cn Boss/OU=$CLIENT_DN_OU/CN=$CLIENT_DN_CN

export SSL_JAVA_HOME=/home/uud/software/jdk1.5.0_06
export JDK_KEYSTORE=$SSL_JAVA_HOME/jre/lib/security/cacerts

#JSSE 信任的CA根憑證的儲存密碼, 似乎不能改變
export JDK_STOREPASS=changeit

export OPENSSL_SRL_FILE=./ca-cert.srl
export CA_ROOT_ALIAS=Boss-CA-ROOT 四、產生CA私密金鑰以及自簽名根憑證, 最後得到PKCS12格式的CA根憑證:

說明:
該命令產生CA私密金鑰以及自簽名根憑證, 最後得到PKCS12格式的CA根憑證(PKCS12格式的CA根憑證受密碼保護, 因此有比較好的安全性);
產生的PKCS12格式的CA根憑證儲存在 dist/ca-cert 目錄下, 在正式使用的系統中, 這個認證檔案(*.pfx)需要妥善儲存,
因為以後的伺服器憑證和用戶端認證都需要依賴這個認證, 尤其是用戶端認證, 如果丟失了CA根憑證,
就無法發布新的用戶端認證了, 而重建CA根憑證, 則需要重建伺服器憑證和用戶端認證,
在用戶端使用者較多的情況下, 重新發布所有的用戶端認證是有相當大的工作量;
在執行這個命令的過程中, 會提示輸入認證保護密碼, 請注意不要遺忘或者泄漏這個密碼, 否則根憑證的安全會受到威脅.

mkdir ca
mkdir dist
cd dist
mkdir ca-cert
cd ..


# genrsa [產生密鑰命令] -out[密鑰檔案輸出路徑] 1024 [密鑰位元]
openssl genrsa -out ca/ca-key.pem 1024

# req[產生認證命令] -new[新產生] -out[認證檔案輸出路徑] -key[私密金鑰檔案路徑]

openssl req -new -out ca/ca-req.csr -key ca/ca-key.pem -subj $CA_DN

# x509[簽發x509認證命令] -req[輸入待簽發認證] -in[輸入待簽發認證檔案路徑] -out[產生x509認證檔案輸出路徑]
# -signkey[自簽發密鑰檔案路徑] -days[認證有效期間]
openssl x509 -req -in ca/ca-req.csr -out ca/ca-cert.pem -signkey ca/ca-key.pem -days 365

# 產生CA認證: ca/ca-cert.pfx, 注意一定要記住匯出密碼:預設為 ssl
# pkcs12[產生PKCS12格式認證命令] -export[匯出檔案] -clerts[僅匯出client認證] -password[匯出密碼]
# -in[輸入的client認證檔案路徑] -inkey[client認證密鑰檔案路徑] -out[匯出PKS12格式檔案路徑]

openssl pkcs12 -export -clcerts -in ca/ca-cert.pem -inkey ca/ca-key.pem -out ca/ca-cert.pfx

# 將產生的認證儲存起來(以後需要用到)
cp ca/ca-cert.pfx dist/ca-cert/ca-cert-200606.pfx

      

五、從PKCS12格式的CA根憑證匯出 CA私密金鑰和未加密CA根憑證

說明:
該命令用於從PKCS12格式的CA根憑證中匯出CA私密金鑰和未加密CA根憑證;
由於安全原因, CA根憑證平時以密碼保護的PKCS12格式檔案(*.pfx)存放,
那麼如果需要使用CA根憑證來發行伺服器認證或者用戶端認證時, 首先需要執行這個命令得到CA根憑證的未加密形式;
在執行這個命令的過程中, 會出現兩次提示輸入根憑證的保護密碼, 如果密碼不正確, 這個命令將不能執行成功,
也就無法進行下面兩步的發布認證的操作了.

mkdir decrypt_ca

# 從PKCS12格式的CA認證匯出不加密的CA認證: ca/ca-cert.pem
openssl pkcs12 -in dist/ca-cert/ca-cert-20060621.pfx -clcerts -nodes -nokeys -out decrypt_ca/ca-cert.pem

# 將得到的認證檔案的開頭四行(Bag Attributes)去掉
# 因為step2-server.bat中keytool import時會認為含有Bag Attributes的檔案"不是一個 X.509 認證"

vi ca-cert.pem
先按 4,再按 dd
最後按 x! 退出檔案編輯

# 從PKCS12格式的CA認證匯出CA私密金鑰: ca/ca-key.pem
openssl pkcs12 -in dist/ca-cert/ca-cert-20060621.pfx -clcerts -nodes -out decrypt_ca/file.pem
openssl rsa -in decrypt_ca/file.pem -out decrypt_ca/ca-key.pem

   

六、產生伺服器端認證

說明:
該命令用於產生伺服器端認證(keystore檔案);
注意: CA根憑證同時也會被匯入到認證的keystore檔案中, 這樣在將這個認證應用到Tomcat Web伺服器上的時候就不需要將CA根憑證
匯入到JSSE的預設位置了;
這個命令必須在執行 (五、從PKCS12格式的CA根憑證匯出 CA私密金鑰和未加密CA根憑證) 之後才能正常運行.

產生KeyPair
mkdir server


# -genkey[產生金鑰組] -alias[金鑰組別名] -validity[密鑰有效期間] -keyalg[密鑰演算法參數] -keysize[密鑰位元]
# -keypass[密鑰保護密碼]- storepass[儲存密碼]
# -dname[別名相關附加資訊,其中cn是伺服器的名字一定要與WEB伺服器中設定的一樣] -keystore[金鑰儲存區檔案路徑]

keytool -genkey -alias $SERVER_ALIAS -validity 720 -keyalg RSA -keysize 1024 -keypass $SERVER_KEYPASS -storepass $SERVER_STOREPASS -dname $SERVER_DNAME -keystore server/$SERVER_KEYSTORE


產生待簽署憑證 server/server.csr
# -certreq[產生待簽署憑證] -alias[認證別名] -sigalg[認證演算法參數] -file [產生檔案輸出路徑]
# -keypass[密鑰保護密碼] -keystore[隱藏檔路徑] -storepass[儲存密碼]

keytool -certreq -alias $SERVER_ALIAS -sigalg MD5withRSA -file server/server.csr -keypass $SERVER_KEYPASS -keystore server/$SERVER_KEYSTORE -storepass $SERVER_STOREPASS


用CA私密金鑰進行簽名, 產生x509認證檔案

# x509[簽發x509認證命令] -req[輸入待簽發認證] -in[輸入待簽發認證檔案路徑] -out[產生x509認證檔案輸出路徑]
# -CA[簽髮根認證] -CAkey[根憑證密鑰檔案] -days[認證有效期間] -CAserial[CA序號檔案]

openssl x509 -req -in server/server.csr -out server/server-cert.pem -CA decrypt_ca/ca-cert.pem -CAkey decrypt_ca/ca-key.pem -days 365 -CAserial $OPENSSL_SRL_FILE -sha1 -trustout


匯入(替換)信任的CA根憑證到JSSE的預設位置(%JDK_KEYSTORE%)


# 匯入前首先刪除(如果原來已經匯入過)
# JSSE 信任的CA根憑證的金鑰儲存區檔案路徑
keytool -delete -v -alias $CA_ROOT_ALIAS -storepass $JDK_STOREPASS -keystore $JDK_KEYSTORE

# -import[匯入命令] -v trustcacerts[匯入信任認證] -storepass[儲存密碼] -alias[CA根憑證的別名]
# -file[認證檔案路徑] -keystore[匯入檔案路徑] -noprompt[不提示"信任這個認證。"]

keytool -import -v -trustcacerts -storepass $JDK_STOREPASS -alias $CA_ROOT_ALIAS -file decrypt_ca/ca-cert.pem -keystore $JDK_KEYSTORE


把CA簽名後的server端認證匯入keystore: server/%SERVER_KEYSTORE%
# -import[匯入命令] -v trustcacerts[匯入信任認證] -storepass[儲存密碼] -keypass[密鑰保護密碼]
# -alias[伺服器憑證的別名] -file[認證檔案路徑] -keystore[匯入檔案路徑]

keytool -import -v -trustcacerts -storepass $SERVER_STOREPASS -keypass $SERVER_KEYPASS -alias $SERVER_ALIAS -file server/server-cert.pem -keystore server/$SERVER_KEYSTORE

把CA根憑證匯入keystore: server/%SERVER_KEYSTORE%
# -import[匯入命令] -v trustcacerts[匯入信任認證] -storepass[儲存密碼] -keypass[密鑰保護密碼]
# -alias[伺服器憑證的別名] -file[認證檔案路徑] -keystore[匯入檔案路徑] -noprompt[不提示"您仍然想要將它添加到自己的keystore 嗎。"]

keytool -import -v -trustcacerts -storepass $SERVER_STOREPASS -keypass $SERVER_KEYPASS -alias $CA_ROOT_ALIAS -file decrypt_ca/ca-cert.pem -keystore server/$SERVER_KEYSTORE


查看JSSE CA根憑證
keytool -list -storepass $JDK_STOREPASS -keystore $JDK_KEYSTORE -alias $CA_ROOT_ALIAS -v

刪除匯入到JSSE的預設位置的CA根憑證(使JDK恢複原狀)
keytool -delete -v -alias $CA_ROOT_ALIAS -storepass $JDK_STOREPASS -keystore $JDK_KEYSTORE


將產生的認證儲存起來(供伺服器使用)
cd dist
mkdir server
cd ..
cp server/$SERVER_KEYSTORE dist/server/$SERVER_KEYSTORE

查看server端認證
keytool -list -storepass $SERVER_STOREPASS -keystore dist/server/$SERVER_KEYSTORE -v

七、發布用戶端認證:

說明:
這個命令用於發布用戶端認證;
為了便於批量產生用戶端認證, 這個命令支援命令列參數, 第1到3個參數依次為:
用戶端認證的名稱(Common Name)
用戶端認證所屬的組織(Organizational Unit Name)
產生的PKS12格式用戶端認證的匯入密碼, 這個密碼可以保護認證只能被知道密碼的使用者匯入到瀏覽器
這個命令必須在執行 (五、從PKCS12格式的CA根憑證匯出 CA私密金鑰和未加密CA根憑證) 之後才能正常運行.

mkdir client

cd dist
mkdir client
cd ..

# 產生client私密金鑰: client/client-key.pem
# genrsa [產生密鑰命令] -out[密鑰檔案輸出路徑] 1024 [密鑰位元]

openssl genrsa -out client/client-key.pem 1024


產生待簽署憑證: client/client-req.csr

# req[產生認證命令] -new[新產生] -out[認證檔案輸出路徑] -key[私密金鑰檔案路徑]
# -subj[request's subject, 這裡放置Distinguished Name(DN)資訊]

openssl req -new -out client/client-req.csr -key client/client-key.pem -subj $CLIENT_DN


用CA私密金鑰進行簽名, 產生x509認證檔案: client/client.crt
# x509[簽發x509認證命令] -req[輸入待簽發認證] -in[輸入待簽發認證檔案路徑] -out[產生x509認證檔案輸出路徑]
# -signkey [密鑰檔案路徑]
# -CA[簽髮根認證] -CAkey[根憑證密鑰檔案] -days[認證有效期間] -CAserial[CA序號檔案]

openssl x509 -req -in client/client-req.csr -out client/client.crt -signkey client/client-key.pem -CA decrypt_ca/ca-cert.pem -CAkey decrypt_ca/ca-key.pem -days 365 -CAserial $OPENSSL_SRL_FILE

產生client端的個人認證: client/$_CLIENT_P12_FILE

# pkcs12[產生PKS12格式認證命令] -export[匯出檔案] -clerts[僅匯出client認證] -password[匯出密碼]
# -in[輸入的client認證檔案路徑] -inkey[client認證密鑰檔案路徑] -out[匯出PKS12格式檔案路徑]
# -name[好記的名字]

密碼是 clientssl
openssl pkcs12 -export -clcerts -in client/client.crt -inkey client/client-key.pem -out client/$CLIENT_DN_OU-$CLIENT_DN_CN.p12 -name $CLIENT_DN_OU-$CLIENT_DN_CN

將產生的認證儲存起來(發布給使用者)
cp client/$CLIENT_DN_OU-$CLIENT_DN_CN.p12 dist/client/$CLIENT_DN_OU-$CLIENT_DN_CN.p12

八、Tomcat 5 伺服器配置:

參考配置方法如下:
將 "六、產生伺服器端認證" 命令產生的 dist/server 目錄下的 keystore 檔案(如果使用預設配置, 這個檔案叫做"boss-alias.keystore")複製到 Tomcat 安裝目錄的 conf 目錄下;
修改 Tomcat 安裝目錄的 conf 目錄下的 "server.xml" 檔案, 修改 <Service name="Catalina"> 包含的 "Connector" 元素, 樣本如下(僅供參考):

<Connector port="8443" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true"
clientAuth="true" sslProtocol="TLS"
URIEncoding="UTF-8"
keystoreFile="%Tomcat%/conf/boss-alias.keystore"
keystorePass="openssl"
truststoreFile="%Tomcat%/conf/boss-alias.keystore"
truststorePass="openssl"/>

九、啟用雙向 SSL 時 Web 應用程式的配置 :

       要啟用雙向 SSL 認證, 在 Web 應用程式的 web.xml 中需要如下增加一些配置: auth-method=CLIENT-CERT 說明是"以用戶端數位憑證來確認使用者的身份", transport-guarantee=CONFIDENTIAL 表示應用程式要求資料必須在一種"防止其他實體看到傳輸的內容的方式中傳送"..

<login-config>
<!-- Authorization setting for SSL -->
<auth-method>CLIENT-CERT</auth-method>
<realm-name>Client Cert Users-only Area</realm-name>
</login-config>
<security-constraint>
<!-- Authorization setting for SSL -->
<web-resource-collection >
<web-resource-name >SSL</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>

十、編寫 JSP 頁面顯示 認證的內容:

      經過以上的配置之後, 那麼即使使用者是通過 http 訪問 Web 應用程式的, 瀏覽器也會自動切換到 https 方式並彈出選擇用戶端認證的對話方塊.
如何使用用戶端認證進行使用者驗證

        在 web 應用程式中, 可以通過 java 代碼從 request 對象中獲得, 根據 Servlet Specifications, 使用request.getAttribute("javax.servlet.request.X509Certificate") 就可以得到 https 請求的用戶端憑證鏈結資訊, 其中第一個元素就是用戶端認證, 相應的範例程式碼如下:

<%@ page import="java.security.cert.X509Certificate"%>
<%
//response.sendRedirect("jsp/vpay/input.jsp");
String certSubject = null;
java.security.cert.X509Certificate[] certChain=
(java.security.cert.X509Certificate[])
request.getAttribute("javax.servlet.request.X509Certificate");
if (null!=certChain){
int len=certChain.length;
if (len>0){
java.security.cert.X509Certificate cert =
(java.security.cert.X509Certificate)certChain[0];
java.security.Principal pSubject = cert.getSubjectDN();
certSubject = pSubject.getName();
}
}
%>
Subject = <%=certSubject%>

 

十一、匯入用戶端認證並訪問 HTTPS 應用:

       匯入用戶端認證到瀏覽器中(雙擊用戶端認證檔案 "W21cn-boss-client-Huaronghu.p12" 即可匯入 IE)。

      匯入完畢後, 啟動 Tomcat, 可以看到 http://localhost:8080/index.jsp 內容的訪問則會自動切換到 https://localhost:8443 上去了; 同時可以看到, 使用 HTTPS 方式訪問時, 用戶端認證的 Subject 可以被 jsp 頁面獲得。

        試著在瀏覽器裡面把匯入的認證刪除, 你會發現 網站的內容已經不能訪問了:

十二、總結:

      當Web伺服器開始正式運行以後, "四、產生CA私密金鑰以及自簽名根憑證, 最後得到PKCS12格式的CA根憑證" 命令是不能再次執行的,
如果需要重新發行者認證, 或者發布新的用戶端認證,
在執行 “六、產生伺服器端認證” 和 “七、產生客戶器端認證” 命令前,
可以通過 “五、從PKCS12格式的CA根憑證匯出 CA私密金鑰和未加密CA根憑證”重新從儲存的PKCS12格式CA根憑證中匯出CA私密金鑰和未加密CA根憑證.

參考資料

http://thinkbase.net/w/main/Wiki?Tomcat5SSL_ServerAndClient

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.