為了實作https協定通信,tomcat需要利用JSSE把SSL/TLS協定內建到自身系統上,通過上一節我們知道不同的廠商可以實作自己的JSSE,而tomcat預設使用的是以前sun公司開發實作的包而且由JDK自帶。
Tomcat實作http及https通信的基礎是什麼?其實http與https的不同就是在建立通信套接字伺服器時的不同,http是沒有任何加密措施的套接字伺服器,而https是靠嵌套了一層密碼機制的套接字伺服器。在實作時隻需根據實際通信情況建立對應的套接字伺服器,這時你應該果斷想起工廠類,由各自工廠負責建立及初始化套接字伺服器。看圖3-1-7-4,在tomcat啟動初始化時其中一個元件JIoEndpoint也會跟着初始化,屆時它将根據配置檔案的SSL辨別來決定建立ServerSocket還是SSLServerSocket。如果是http協定則使用DefaultServerSocketFactory完成套接字伺服器建立,反之,如果是https協定則要通過SSLImplementation間接定位到JSSESocketFactory,由它完成套接字伺服器的建立。

圖3-1-7-4 http與https套接字工廠類
關于http協定使用的套接字這裡我們并不關心,重點研究下https協定使用的安全套接字的生成及相關操作,具體由JSSESocketFactory實作,此工廠類擴充了兩個接口,其中ServerSocketFactory接口定義建立套接字、開始接受套接字、握手等方法,另外的SSLUtil接口則定義了一些SSL相關對象(例如SSL上下文、密鑰管理器、信任管理器等)的操作方法。在tomcat啟動時将通過createSocket方法建立安全套接字伺服器,如下
public ServerSocket createSocket (int port) throws IOException{
init();
ServerSocket socket = sslProxy.createServerSocket(port);
initServerSocket(socket);
return socket;
}
首先,init()方法作為初始化方法進行一些初始化操作,包括建立SSL上下文、利用密鑰管理器和信任管理器初始化SSL上下文、設定SSL會話、檢測SSL配置是否OK等等,經過上一節的學習,這一系列操作相信大家都比較熟悉了,都是JSSE API的一些操作。接着,通過sslProxy建立SSLServerSocket,sslProxy其實是SSLServerSocketFactory類的執行個體,此類屬于JSSE API的核心類,不必往下追究createServerSocket的詳細實作。然後,通過initServerSocket方法對剛剛建立的SSLServerSocket做一些初始化操作,包括設定可用的加密套件、設定可用的協定、設定是否需要用戶端提供身份驗證等等。最後,傳回SSLServerSocket對象,即安全套接字伺服器對象。
除了createSocket方法之外,JSSESocketFactory還有幾個重要的方法需要說明一下:
① handshake方法,它負責執行SSL握手,一般握手可以通過SSLSocket的startHandshake()方法或getSession()方法實作,startHandshake是一種顯式的調用,它将使會話使用心得密鑰、新的加密套件。而getSession則是一種隐式的調用,它會判斷目前是否存在有效會話,如果沒有則嘗試建立會話。JSSESocketFactory的handshake方法選擇通過getSession方法隐式實作。
② getKeystorePassword方法,它負責擷取密鑰存儲器密碼,tomcat将密碼預設設為“changeit”,在實際運作中,如果server.xml的connector節點配置了keystorePass,則密碼為這個keystorePass,如果配置了keyPass而沒有配置keystorePass則密碼為keyPass,否則最後才是使用預設密碼“changeit”。
③ getKeystore方法,它負責讀取密鑰存儲器,密鑰存儲器的預設檔案路徑是System.getProperty("user.home")即使用者目錄下的.keystore檔案,如果server.xml的connector節點配置了keystoreFile,則路徑為指定的keystoreFile,否則使用預設路徑。
④ checkConfig方法,它負責檢查證書與啟用的密碼套件是否相容,主要是為了解決編号為45528的bug,檢測的方法比較巧妙,建立了一個沒有綁定任何端口的SSLServerSocket對象,逾時設定為1毫秒,接着調用accept方法,一毫秒後肯定會抛出一個異常,因為綁定端口肯定不會被用戶端連上,1毫秒後肯定會逾時,是以它有兩種可能,一種是證書與密碼套件有相容問題則會抛出SSLException異常,另外一種則是抛出逾時異常。根據不同異常處理即可。
經過上一節的JSSE學習後,這節關于tomcat的ssl安全信道實作則很好了解,無非就是把JSSE的接口內建到tomcat的核心程式中。
<a target="_blank" href="https://item.jd.com/12185360.html">點選訂購作者《Tomcat核心設計剖析》</a>