@[TOC](Java Secure Socket Extension (JSSE) -类和接口篇 )

为了 通信安全,两侧的连接必须是SSL-enabled。JSSE API里,连接的endpoint类是SSLSocket和SSLEngine。

Java Secure Socket Extension (JSSE) -类和接口篇

SSLSocketFactory或者SSLServerSocket生成的SSLSocket,接收入站连接。
SSLServerSocket由SSLServerSocketFactory增加。SSLSocketFactory和SSLServerSocketFactory对象由SSLContext生成。
SSLEngine由SSLContext直接生成,依靠这些处理全部I/O。

注意
使用原生的SSLSocket和SSLEngine类的时候,在发送数据之前,你总是应该检查对方的证书。从JDK 7开始,endpoint识别/验证过程可以在SSL/TLS握手期间处理。见方法SSLParameters.setEndpointIdentificationAlgorithm。
例如,URL里的主机名应该和对方证书里的主机名匹配。如果不校验主机名,程序可以进行URL欺骗攻击。

SocketFactory and ServerSocketFactory Classes

抽象的javax.net.SocketFactory类用来增加sockets。它的子类是增加特定sockets的工厂,这样提供了一个添加公共socket级功能的通用框架。
抽象的javax.net.ServerSocketFactory类类似SocketFactory类,但是,只能用来增加服务器sockets。
Socket工厂是捕获与正在构造的sockets相关的各种策略简单的办法,这样生成sockets,不需要特定的配置代码:

  • 通过工厂和sockets的多态性,不同类型的sockets可以使用相同的程序代码,仅仅传给不同类型的工厂
  • 工厂使用构造socket时的参数,定制自己。比如,工厂返回的sockets可以有不同的网络超时或者其他安全参数
  • 程序返回的sockets可以是java.net.Socket(或者javax.net.ssl.SSLSocket)的子类,这样可以直接暴露新的API,比如压缩、安全、打标签、统计或者防火墙隧道。

javax.net.ssl.SSLSocketFactory是增加安全sockets的工厂,是抽象类javax.net.SocketFactory的子类。安全socket工厂封装了增加和初始化配置安全sockets的细节。包括认证keys,对端证书骄傲眼、确定密码套件等。
javax.net.ssl.SSLServerSocketFactory类类似SSLSocketFactory类,但是用来增加服务器sockets。

Obtaining an SSLSocketFactory

使用下列办法获得SSLSocketFactory:

  • 使用SSLSocketFactory.getDefault()静态方法获得默认的工厂
  • 把工厂作为一个API参数。这样做,生成sockets的代码,不用关心配置sockets的细节,可以包括一个带SSLSocketFactory参数的方法。可以由客户端在增加sockets的时候调用(比如 javax.net.ssl.HttpsURLConnection)。
  • 使用特定的配置行为构造一个新工厂

默认工厂支持服务器认证的典型配置,所以,默认工厂增加的sockets不会比普通的TCP socket泄漏更多的客户端信息。
增加和使用sockets的很多类不需要知道socket生成行为的细节。
你可以或者实现自己的socket工厂子类,或者使用另一个类作为socket工厂的工厂来增加新的socket工厂实例。比如SSLContext就是这样一个类。

SSLSocket and SSLServerSocket Classes

javax.net.ssl.SSLSocket类是标准的java.net.Socket类的子类。它支持全部的标准socket的方法,增加了安全sockets的特定方法。该类的实例封装了SSLContext。它有为socket实例增加安全的sessions的API,但是trust和key管理没有被直接暴露。
javax.net.ssl.SSLServerSocket用来增加服务器sockets。
为了防止对方欺骗,应该总是验证SSLSocket的证书。

注意:由于SSL和TLS协议的复杂性,很难预测从连接接收的信息是握手信息还是程序数据,数据的不同可能影响当前的连接状态(甚至导致过程的结束)。Oracle的JSSE实现里,通过SSLSocket.getInputStream()获得的对象的available()方法返回从SSL连接解密的还没有读取的程序数据的字节数。

Obtaining an SSLSocket

有两种办法获得SSLSocket实例:

  • SSLSocketFactory实例的几个createSocket方法
  • SSLServerSocket类的accept方法

Cipher Suite Choice and Remote Entity Verification

SSL/TLS协议定义一系列步骤确保受保护的连接。cipher suite的选择直接影响连接的安全类型。例如,如果选择了匿名的cipher suite,程序就没办法校验对方的身份。如果选择了不加密的suite,就不能保护数据的隐私。另外,SSL/TLS协议没规定接收的证书必须匹配对方可能期望发送的。如果连接不知何故重定向到一个流氓端,而流氓的证书基于当前的trust资料被接受了,会认为连接是有效的。
当使用原生的SSLSocket和SSLEngine类的时候,你应该总是在发送数据之前检查对方的证书。SSLSocket和SSLEngine类不自动校验URL里的主机名是否和对方证书里的主机名匹配。如果不校验主机名,程序可能被URL欺骗所利用。从JDK 7开始,endpoint识别/验证过程能在SSL/TLS期间被处理。
比如HTTPS协议不需要主机名校验。从JDK 7开始,默认地,HTTPS endpoint识别在握手期间由HttpsURLConnection强制执行。见SSLParameters.getEndpointIdentificationAlgorithm方法。另外,程序可以使用HostnameVerifier接口覆盖默认的HTTPS主机名规则。见HostnameVerifier接口和HttpsURLConnection类。

相关文章:

  • 2021-12-19
  • 2021-04-15
  • 2021-06-19
  • 2021-09-11
  • 2021-10-20
  • 2021-10-24
猜你喜欢
  • 2021-12-29
  • 2021-11-17
  • 2021-06-24
  • 2021-12-03
  • 2021-07-16
  • 2021-08-20
相关资源
相似解决方案