前言
整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。
開源專案
從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。
系列文章
web server apache tomcat11-01-官方文件入門介紹
web server apache tomcat11-02-setup 啟動
web server apache tomcat11-03-deploy 如何部署
web server apache tomcat11-04-manager 如何管理?
web server apache tomcat11-06-Host Manager App -- Text Interface
web server apache tomcat11-07-Realm Configuration
web server apache tomcat11-08-JNDI Resources
web server apache tomcat11-09-JNDI Datasource
web server apache tomcat11-10-Class Loader
...
快速開始
下面的描述使用變數名 $CATALINA_BASE
來引用大多數相對路徑解析的基本目錄。如果您尚未透過設定 CATALINA_BASE
目錄來為 Tomcat 配置多個例項,則 $CATALINA_BASE
將設定為 $CATALINA_HOME
的值,即您安裝 Tomcat 的目錄。
要在 Tomcat 上安裝和配置 SSL/TLS 支援,您需要遵循以下簡單步驟。有關更多資訊,請閱讀本指南的其餘部分。
建立金鑰庫檔案
執行以下命令建立用於儲存伺服器的私鑰和自簽名證書的金鑰庫檔案:
Windows:
"%JAVA_HOME%\bin\keytool" -genkey -alias tomcat -keyalg RSA
Unix:
$JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA
並指定密碼值為 "changeit"。
修改配置檔案
取消註釋 $CATALINA_BASE/conf/server.xml
中的 "SSL HTTP/1.1 Connector" 條目,並按照下面的配置部分所述進行修改。
SSL/TLS 簡介
傳輸層安全性(TLS)及其前身安全套接字層(SSL)是使 Web 瀏覽器和 Web 伺服器能夠透過安全連線進行通訊的技術。這意味著傳送的資料由一方加密,然後傳輸,然後由另一方在處理之前解密。這是一個雙向過程,這意味著伺服器和瀏覽器都會在傳送資料之前對所有流量進行加密。
SSL/TLS 協議的另一個重要方面是認證。這意味著在您首次嘗試透過安全連線與 Web 伺服器通訊時,該伺服器將向您的 Web 瀏覽器提供一組憑據,以證明該站點是誰以及它聲稱的內容。在某些情況下,伺服器還可能要求您的 Web 瀏覽器提供證書,以證明您是您所聲稱的人。這稱為 "客戶端認證",儘管在實踐中,這更多用於業務對業務(B2B)交易而不是與個人使用者。大多數啟用 SSL 的 Web 伺服器不會請求客戶端認證。
證書
為了實施 SSL,Web 伺服器必須為接受安全連線的每個外部介面(IP 地址)準備一個相關聯的證書。這個設計背後的理論是伺服器應該提供某種合理的保證,證明其所有者是您認為的那個人,特別是在接收任何敏感資訊之前。雖然證書的廣泛解釋超出了本文件的範圍,但將證書視為一個 Internet 地址的 "數字護照"。它說明了該站點與哪個組織相關聯,以及關於站點所有者或管理員的一些基本聯絡資訊。
這個證書由其所有者以密碼形式簽名,因此其他人很難偽造。為了使證書在訪客的瀏覽器中無警告地工作,它需要由受信任的第三方簽名。這些被稱為證書頒發機構(CA)。要獲得簽名的證書,您需要選擇一個 CA,並按照您選擇的 CA 提供的說明來獲取您的證書。有各種各樣的 CA 可供選擇,包括一些免費提供證書的 CA。
Java 提供了一個相對簡單的命令列工具,稱為 keytool,可以輕鬆建立 "自簽名" 證書。自簽名證書只是使用者生成的未經 well-known CA 簽名的證書,因此不真正保證是真實的。雖然自簽名證書可能對某些測試場景有用,但對於任何形式的生產使用都不合適。
執行 SSL 的一般提示
在使用 SSL 保護網站時,重要的是確保網站使用的所有資源都透過 SSL 提供,以防止攻擊者透過在 JavaScript 檔案中注入惡意內容等方式繞過安全性。為了進一步增強網站的安全性,您應該考慮使用 HSTS 標頭。它允許您向瀏覽器通訊,指示您的站點應始終透過 https 訪問。
在安全連線上使用基於名稱的虛擬主機需要謹慎配置單個證書中指定的名稱,或者在支援 Server Name Indication(SNI)的 Tomcat 8.5 及更高版本中,其中可用。SNI 允許將具有不同名稱的多個證書關聯到單個 TLS 聯結器。
配置
準備證書金鑰庫
Tomcat 目前僅支援 JKS、
PKCS11 或 PKCS12 格式的金鑰庫。JKS 格式是 Java 的標準 "Java KeyStore" 格式,是 keytool 命令列實用程式建立的格式。此工具包含在 JDK 中。PKCS12 格式是一種網際網路標準,可以透過 OpenSSL 和 Microsoft 的 Key-Manager 等方式進行操作。
金鑰庫中的每個條目都由別名字串標識。雖然許多金鑰庫實現以不區分大小寫的方式處理別名,但也可用區分大小寫的實現。例如,PKCS11 規範要求別名區分大小寫。為了避免與別名的大小寫敏感性相關的問題,不建議使用僅在大小寫方面有所不同的別名。要匯入現有證書到 JKS 金鑰庫,請閱讀(在您的 JDK 文件包中)有關 keytool 的文件。請注意,OpenSSL 通常會在金鑰之前新增可讀的註釋,但 keytool 不支援。因此,如果您的證書在金鑰資料之前有註釋,請在使用 keytool 匯入證書之前將其刪除。
要使用 OpenSSL 將現有 CA 簽名的證書匯入 PKCS12 金鑰庫,您可以執行類似於以下命令:
openssl pkcs12 -export -in mycert.crt -inkey mykey.key
-out mycert.p12 -name tomcat -CAfile myCA.crt
-caname root -chain
對於更高階的情況,請參閱 OpenSSL 文件。
要從頭開始建立一個新的 JKS 金鑰庫,其中包含一個單獨的自簽名證書,請從終端命令列執行以下操作:
Windows:
"%JAVA_HOME%\bin\keytool" -genkey -alias tomcat -keyalg RSA
Unix:
$JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA
(RSA 演算法應優先選擇作為安全演算法,這還確保與其他伺服器和元件的一般相容性。)
此命令將在您執行它的使用者的主目錄中建立一個名為 .keystore
的新檔案。要指定不同的位置或檔名,請將 -keystore
引數新增到上面顯示的 keytool 命令,後面跟上到您金鑰庫檔案的完整路徑名。您還需要在後面描述的 server.xml
配置檔案中反映這個新位置。例如:
Windows:
"%JAVA_HOME%\bin\keytool" -genkey -alias tomcat -keyalg RSA
-keystore \path\to\my\keystore
Unix:
$JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA
-keystore /path/to/my/keystore
執行此命令後,您首先會提示輸入金鑰庫密碼。Tomcat 使用的預設密碼是 "changeit"(全部小寫),儘管您可以指定自定義密碼。您還需要在後面描述的 server.xml
配置檔案中指定自定義密碼。
接下來,您將提示提供有關此證書的一般資訊,例如公司、聯絡人姓名等。將顯示此資訊以便嘗試訪問您應用程式中的安全頁面的使用者,請確保此處提供的資訊與他們預期的相匹配。
最後,您將被提示輸入金鑰密碼,這是專門為此證書(而不是儲存在同一金鑰庫檔案中的任何其他證書)的密碼。keytool 提示將告訴您,按 ENTER 鍵會自動使用與金鑰庫相同的密碼來使用金鑰。您可以自由選擇相同的密碼或選擇自定義密碼。如果您選擇與金鑰庫密碼不同的密碼,則還需要在後面描述的 server.xml
配置檔案中指定自定義密碼。
如果一切順利,現在您有一個帶有證書的金鑰庫檔案,該證書可供您的伺服器使用。
編輯 Tomcat 配置檔案
Tomcat 可以使用兩種不同的 SSL 實現:
- 作為 Java 執行時的一部分提供的 JSSE 實現
- 使用 OpenSSL 的 JSSE 實現
確切的配置細節取決於使用的是哪種實現。如果透過指定通用 protocol="HTTP/1.1"
配置聯結器,則 Tomcat 使用的實現將自動選擇。
如果需要,可以透過在聯結器的 protocol
屬性中指定類名來避免自動選擇實現。
要定義 Java(JSSE)聯結器,無論 APR 庫是否已載入,請使用以下之一:
<!-- 在埠 8443 上定義 HTTP/1.1 聯結器,JSSE NIO 實現 -->
<Connector protocol="org.apache.coyote.http11.Http11NioProtocol"
sslImplementationName="org.apache.tomcat.util.net.jsse.JSSEImplementation"
port="8443" .../>
<!-- 在埠 8443 上定義 HTTP/1.1 聯結器,JSSE NIO2 實現 -->
<Connector protocol="org.apache.coyote.http11.Http11Nio2Protocol"
sslImplementationName="org.apache.tomcat.util.net.jsse.JSSEImplementation"
port="8443" .../>
如果需要,也可以顯式配置 OpenSSL JSSE 實現。如果安裝了 Tomcat Native 庫或 Java 22,則使用 sslImplementationName
屬性可以啟用它。當使用 OpenSSL JSSE 實現時,配置可以使用 JSSE 屬性或 OpenSSL 屬性,但不得在相同的 SSLHostConfig
或 Connector
元素中混合使用來自兩種型別的屬性。
使用 Tomcat Native:
<!-- 在埠 8443 上定義 HTTP/1.1 聯結器,JSSE NIO 實現和 OpenSSL -->
<Connector protocol="org.apache.coyote.http11.Http11NioProtocol" port="8443"
sslImplementationName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation"
.../>
使用 Java 22 FFM API:
<!-- 在
埠 8443 上定義 HTTP/1.1 聯結器,JSSE NIO 實現和 OpenSSL -->
<Connector protocol="org.apache.coyote.http11.Http11NioProtocol" port="8443"
sslImplementationName="org.apache.tomcat.util.net.openssl.panama.OpenSSLImplementation"
.../>
或者,可以向伺服器新增偵聽器以在不必在每個 SSLHostConfig 或 Connector 元素上新增 sslImplementationName
屬性的情況下在所有聯結器上啟用 OpenSSL。
使用 Tomcat Native:
<Listener className="org.apache.catalina.core.AprLifecycleListener"/>
使用 Java 22 FFM API:
<Listener className="org.apache.catalina.core.OpenSSLLifecycleListener"/>
偵聽器的 SSLRandomSeed
屬性允許指定一個熵源。生產系統需要可靠的熵源,但熵可能需要大量時間才能收集,因此測試系統可以使用無阻塞熵源,如 "/dev/urandom",這將允許 Tomcat 更快地啟動。
最後一步是在 $CATALINA_BASE/conf/server.xml
檔案中配置聯結器,其中 $CATALINA_BASE
表示 Tomcat 例項的基目錄。預設的 server.xml
檔案中包含了一個 SSL 聯結器的示例 <Connector>
元素。要配置使用 JSSE 並且使用 JSSE 配置樣式的 SSL 聯結器,您需要刪除註釋並編輯它,使其看起來像這樣:
<!-- 在埠 8443 上定義一個 SSL Coyote HTTP/1.1 聯結器 -->
<Connector
protocol="org.apache.coyote.http11.Http11NioProtocol"
port="8443"
maxThreads="150"
SSLEnabled="true">
<SSLHostConfig>
<Certificate
certificateKeystoreFile="${user.home}/.keystore"
certificateKeystorePassword="changeit"
type="RSA"
/>
</SSLHostConfig>
</Connector>
OpenSSL 配置樣式使用許多 SSL 設定的不同屬性,特別是金鑰和證書。APR 配置樣式的示例是:
<!-- 在埠 8443 上定義一個 SSL Coyote HTTP/1.1 聯結器 -->
<Connector
protocol="org.apache.coyote.http11.Http11NioProtocol"
port="8443"
maxThreads="150"
SSLEnabled="true" >
<SSLHostConfig>
<Certificate
certificateKeyFile="conf/localhost-rsa-key.pem"
certificateFile="conf/localhost-rsa-cert.pem"
certificateChainFile="conf/localhost-rsa-chain.pem"
type="RSA"
/>
</SSLHostConfig>
</Connector>
配置選項和關於哪些屬性是強制的資訊,都記錄在 HTTP 聯結器配置參考的 SSL 支援部分中。Tomcat 使用所有 TLS 聯結器支援任一配置樣式(JSSE 或 OpenSSL)。
port
屬性是 Tomcat 將偵聽安全連線的 TCP/IP 埠號。您可以將其更改為任何您希望的埠號(例如,預設的 https 通訊埠 443)。但是,在許多作業系統上執行 Tomcat 的埠號低於 1024 需要特殊設定(超出了本文件的範圍)。
如果在這裡更改了埠號,則還應更改非 SSL 聯結器上指定的 redirectPort
屬性的值。這允許 Tomcat 自動重定向試圖訪問具有指定了 SSL 為必需的安全約束的頁面的使用者,如 Servlet 規範所要求的那樣。
完成這些配置更改後,您必須像平常一樣重新啟動 Tomcat,然後您應該可以執行了。您應該能夠透過 SSL 訪問 Tomcat 支援的任何 Web 應用程式。例如,請嘗試:
https://localhost:8443/
您應該看到通常的 Tomcat 啟動頁面(除非您已修改了 ROOT Web 應用程式)。如果這不起作用,請參閱以下部分中的一些故障排除提示。
安裝來自證書頒發機構的證書
要獲取並安裝來自證書頒發機構(如 verisign.com、thawte.com 或 trustcenter.de)的證書,請閱讀上一節,然後按照以下說明操作:
建立本地證書籤名請求(CSR)
為了從您選擇的證書頒發機構那裡獲得證書,您必須建立一個名為證書籤名請求(CSR)的請求。該 CSR 將由證書頒發機構用於建立將您的網站標識為 "安全" 的證書。要建立 CSR,請執行以下步驟:
- 建立本地自簽名證書(如上一節中所述):
keytool -genkey -alias tomcat -keyalg RSA
-keystore <your_keystore_filename>
(在某些情況下,您必須在 "姓" 欄位中輸入您網站的域名(即 www.myside.org),以便建立可用的證書。)
然後使用以下命令建立 CSR:
keytool -certreq -keyalg RSA -alias tomcat -file certreq.csr
-keystore <your_keystore_filename>
現在您有一個名為 certreq.csr 的檔案,您可以將其提交給證書頒發機構(檢視證書頒發機構網站上關於如何執行此操作的文件)。
機構將使用此 CSR 建立您的證書。
從證書頒發機構獲得證書
在收到您的 CSR 後,證書頒發機構將向您傳送一個檔案(通常以 PEM 格式),其中包含您的新證書。
安裝證書
一旦您從證書頒發機構那裡收到了新的證書檔案,您可以將其新增到您的金鑰庫檔案中。首先,請將檔案轉換為與金鑰庫相容的格式,然後再將其新增到金鑰庫中。這是一個示例命令序列,假設您收到的檔案是以 PEM 格式編寫的。
要將 PEM 檔案轉換為 PKCS12 檔案,請執行以下操作:
openssl pkcs12 -export -in cert.pem -out cert.p12 -name tomcat
然後將 PKCS12 檔案匯入到您的金鑰庫中:
keytool -importkeystore -deststorepass <your_keystore_password>
-destkeypass <your_keystore_password>
-destkeystore <your_keystore_filename> -srckeystore cert.p12
-srcstoretype PKCS12 -srcstorepass <password_used_when_creating_pkcs12> -alias tomcat
現在,您的金鑰庫中應該包含來自證書頒發機構的證書。現在可以在 Tomcat 配置檔案中使用該金鑰庫(如上所示)。
最後的步驟
安裝證書後,請確保您的使用者將 $CATALINA_BASE/conf/server.xml
檔案和您的金鑰庫檔案保持安全。私鑰庫檔案中的私鑰和金鑰庫密碼都是敏感資訊,不應與他人共享。
完成所有配置更改後,必須重新啟動 Tomcat 伺服器才能使更改生效。您應該能夠透過安全的 HTTPS 連線訪問您的 Tomcat 伺服器了。
參考資料
https://tomcat.apache.org/tomcat-11.0-doc/ssl-howto.html