Tomcat中的ssl安全信道的实现
为了实现https协议通信,tomcat须要利用JSSE把SSL/TLS协议集成到自身系统上,通过上一节我们知道不同的厂商能够实现自己的JSSE,而tomcat默认使用的是曾经sun公司开发实现的包并且由JDK自带。
Tomcat实现http及https通信的基础是什么?事实上http与https的不同就是在创建通信套接字server时的不同,http是没有不论什么加密措施的套接字server。而https是靠嵌套了一层password机制的套接字server。在实现时仅仅需依据实际通信情况创建相应的套接字server,这时你应该果断想起工厂类,由各自工厂负责创建及初始化套接字server。看图3-1-7-4,在tomcat启动初始化时当中一个组件JIoEndpoint也会跟着初始化,届时它将依据配置文件的SSL标识来决定创建ServerSocket还是SSLServerSocket。
假设是http协议则使用DefaultServerSocketFactory完毕套接字server创建,反之,假设是https协议则要通过SSLImplementation间接定位到JSSESocketFactory,由它完毕套接字server的创建。
图3-1-7-4 http与https套接字工厂类
关于http协议使用的套接字这里我们并不关心,重点研究下https协议使用的安全套接字的生成及相关操作,具体由JSSESocketFactory实现。此工厂类扩展了两个接口,当中ServerSocketFactory接口定义创建套接字、開始接受套接字、握手等方法,另外的SSLUtil接口则定义了一些SSL相关对象(比如SSL上下文、密钥管理器、信任管理器等)的操作方法。在tomcat启动时将通过createSocket方法创建安全套接字server,例如以下
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做一些初始化操作。包含设置可用的加密套件、设置可用的协议、设置是否须要client提供身份验证等等。
最后。返回SSLServerSocket对象,即安全套接字server对象。
除了createSocket方法之外。JSSESocketFactory还有几个重要的方法须要说明一下:
① handshake方法。它负责执行SSL握手。一般握手能够通过SSLSocket的startHandshake()方法或getSession()方法实现。startHandshake是一种显式的调用。它将使会话使用心得密钥、新的加密套件。
而getSession则是一种隐式的调用。它会推断当前是否存在有效会话,假设没有则尝试建立会话。
JSSESocketFactory的handshake方法选择通过getSession方法隐式实现。
② getKeystorePassword方法,它负责获取密钥存储器password,tomcat将password默认设为“changeit”,在实际执行中,假设server.xml的connector节点配置了keystorePass。则password为这个keystorePass,假设配置了keyPass而没有配置keystorePass则password为keyPass。否则最后才是使用默认password“changeit”。
③ getKeystore方法,它负责读取密钥存储器,密钥存储器的默认文件路径是System.getProperty("user.home")即用户文件夹下的.keystore文件,假设server.xml的connector节点配置了keystoreFile,则路径为指定的keystoreFile,否则使用默认路径。
④ checkConfig方法,它负责检查证书与启用的password套件是否兼容。主要是为了解决编号为45528的bug,检測的方法比較巧妙,创建了一个没有绑定不论什么端口的SSLServerSocket对象,超时设置为1毫秒。接着调用accept方法,一毫秒后肯定会抛出一个异常,由于绑定端口肯定不会被client连上,1毫秒后肯定会超时。所以它有两种可能。一种是证书与password套件有兼容问题则会抛出SSLException异常,第二种则是抛出超时异常。依据不同异常处理就可以。
经过上一节的JSSE学习后。这节关于tomcat的ssl安全信道实现则非常好理解。无非就是把JSSE的接口集成到tomcat的核心程序中。