SSL套接字连接在Java中得到很好的支持,对于您来说可能是一个不错的选择。事先要了解的一件事是,SSL同时提供加密和服务器身份验证。您不能轻易获得仅加密。作为参考,加密可以防止网络窃听,而服务器身份验证可以防止“中间人”攻击,在这种情况下,攻击者充当客户端和服务器之间的代理。
由于身份验证是SSL不可或缺的一部分,因此服务器将需要提供SSL证书,而客户端将需要能够对证书进行身份验证。服务器将需要一个“密钥库”文件来存储其证书。客户端将需要一个“信任存储”文件,在该文件中存储其信任的证书,其中之一必须是服务器的证书,或者可以从中追溯“信任链”的证书到服务器的证书。
请注意,您不必了解SSL的来龙去脉即可使用Java
SSL套接字。我确实认为通读SSL的工作方式很有意思,例如在Wikipedia上有关TLS的文章中,但是复杂的多步握手和实际连接加密的设置都由SSLServerSocket和SSLSocket类在幕后处理。
代码
以上所有内容只是背景信息,它解释了以下一些代码。该代码假定您熟悉常规的未加密套接字。在服务器上,您将需要如下代码:
ServerSocket getSSLServerSocket( File keyStoreFile, char[] keyStoreFilePassword, int port) throws GeneralSecurityException, IOException { SSLContext sslContext = SSLConnections.getSSLContext(keyStoreFile, keyStoreFilePassword); SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory(); SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(port); return sslServerSocket;}然后可以像使用其他任何ServerSocket一样使用SSLServerSocket;身份验证,加密和解密将对调用代码完全透明。实际上,我自己的代码中的关联函数声明的返回类型仅为纯ServerSocket,因此调用代码不会感到困惑。
注意:如果要将JRE的默认cacerts文件用作密钥存储文件,则可以跳过创建SSLContext的行,并使用它
ServerSocketFactory.getDefault()来获取ServerSocketFactory。您仍将服务器的公用/专用密钥对安装到密钥存储文件中,在本例中为
cacerts文件。
在客户端上,您将需要如下代码:
SSLSocket getSSLSocket( File trustStoreFile, char[] trustStoreFilePassword, InetAddress serverAddress, port serverPort) throws GeneralSecurityException, IOException { SSLContext sslContext = SSLConnections.getSSLContext(trustStoreFile, trustStoreFilePassword); SSLSocket sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket (serverAddress, serverPort); sslSocket.startHandshake(); return sslSocket;}就像服务器代码中的SSLServerSocket一样,这里返回的SSLSocket就像常规的Socket一样使用;进入和退出SSLSocket的I /
O是使用未加密的数据完成的,所有加密工作都是在内部完成的。
与服务器代码一样,如果要使用默认的JRE
cacerts文件作为信任库,则可以跳过SSLContext的创建并使用
SSLSocketFactory.getDefault()代替
sslContext.getSocketFactory()。在这种情况下,仅当服务器的证书是自签名的或不是由主要认证机构之一签发的,才需要安装服务器的证书。另外,为确保您不信任在您信任的证书链中合法发行的证书,而是将其信任的域与尝试访问的域完全不同,则应在该行之后添加以下(未嵌套的)代码您在哪里创建
SSLSocket:
sslSocket.getSSLParameters().setEndpointIdentificationAlgorithm("HTTPS");如果您使用自己的信任库文件,但信任该文件中一个或多个证书颁发机构颁发的所有证书,或者信任该文件中不同服务器的许多证书,则这也适用。
证书,密钥库和信任库
现在,对于困难的或至少稍微困难的部分:生成和安装证书。我建议使用Java
keytool(最好是1.7或更高版本)来完成这项工作。
如果要创建自签名证书,请首先使用以下命令从命令行生成服务器的密钥对:
keytool -genkey -alias server -keyalg rsa-dname "cn=server, ou=unit, o=org, l=City, s=ST, c=US" -validity 365242-keystore server_key_store_file -ext san=ip:192.168.1.129-v。替换您自己的名称和值。特别是,此命令为IP地址为192.168.1.129的服务器创建一个密钥对,该密钥对在365242天(即1000年)内到期。如果客户端将通过域名系统查找服务器,请使用
san=dns:server.example.com代替
san=ip:192.168.1.129。有关keytool选项的更多信息,请使用
mankeytool。
系统将提示您输入密钥库的密码-如果这是新的密钥库文件,则设置密钥库的密码-并设置新密钥对的密码。
现在,使用导出服务器的证书
keytool -export -alias server -file server.cer -keystoreserver_key_store_file -rfc -v。这将创建一个
server.cer包含证书以及服务器公共密钥的文件。
最后,将server.cer文件移动到客户端计算机,然后使用诸如此类将证书安装到客户端的信任存储中
keytool -import -aliasserver -file server.cer -keystore client_trust_store_file-v。系统将提示您输入信任存储文件的密码。提示将显示“输入密钥库密码”,因为Java密钥工具可同时用于密钥库文件和信任库文件。请注意,如果您使用的是默认JRE
cacerts文件
changeit,我相信初始密码是。
如果您正在使用从公认的证书颁发机构购买的证书,并且正在
cacerts客户端上使用默认的JRE
文件,则只需将证书安装在服务器的密钥存储文件中;您不必弄乱客户端的文件。服务器安装说明应由证书颁发机构提供,或者您也可以再次查看
mankeytool说明。
关于套接字,尤其是SSL套接字,存在大量的神秘知识,但是它们实际上非常易于使用。在许多情况下,十行代码将避免需要复杂而脆弱的消息传递或消息排队基础结构。适合您考虑使用此选项。



