- java.lang.Object
-
- javax.net.ssl.SSLEngine
-
public abstract class SSLEngine extends Object
一种使用协议(如安全套接字层(SSL)或IETF RFC 2246 "Transport Layer Security" (TLS)协议)进行安全通信的类,但是是独立的传输。安全通信模式包括:
- 诚信保障 SSL / TLS / DTLS可防止活动的窃听器修改消息。
- 认证 。 在大多数模式下,SSL / TLS / DTLS提供对等认证。 服务器通常被认证,客户端可以根据服务器的要求进行身份验证。
- 保密(隐私保护) 。 在大多数模式下,SSL / TLS / DTLS加密在客户端和服务器之间发送的数据。 这样可以保护数据的机密性,从而使被动窃听者不会看到诸如财务信息或者个人信息等敏感数据。
所使用的密码套件是通过称为“握手”的协商过程建立的。 此过程的目标是创建或重新加入“会话”,可以保护多个连接。 握手完成后,您可以使用
getSession()
方法访问会话属性。SSLSocket
类提供了大量相同的安全功能,但是所有入站和出站数据都将使用底层的Socket
进行自动传输,设计使用阻塞模型。 虽然这适用于许多应用程序,但该模型不提供大型服务器所需的可扩展性。SSLEngine
的主要区别在于它独立于传输机制对入站和出站字节流进行操作。SSLEngine
用户有责任安排可靠的I / O传输到对端。 通过分离SSL / TLS / DTLS从I / O传输机制抽象化,所述SSLEngine
可用于各种各样的I / O类型的,例如non-blocking I/O (polling)
,selectable non-blocking I/O
,Socket
与传统的输入/ OutputStreams,本地ByteBuffers
或字节数组, future asynchronous I/O models等。在高层次,
SSLEngine
出现:app data | ^ | | | v | | +----+-----|-----+----+ | | | | SSL|Engine | wrap() | | | unwrap() | OUTBOUND | INBOUND | | | | +----+-----|-----+----+ | | ^ | | | v | net data
应用程序数据(也称为明文或明文)是由应用程序生成或使用的数据。 其对应的是网络数据,它由握手和/或密文(加密)数据组成,并且预定通过I / O机制传输。 入站数据是从对等体接收到的数据,出站数据指定给对等体。(在
SSLEngine
的上下文中,术语“握手数据”被认为是指交换的任何数据,以建立和控制安全连接。握手数据包括SSL / TLS / DTLS消息“alert”,“change_cipher_spec”和“handshake “。)有
SSLEngine
有五个不同的阶段。- 创建 -
SSLEngine
已创建和初始化,但尚未使用。 在此阶段,应用程序可以设置任何SSLEngine
特定设置(启用的密码套件,无论SSLEngine
是否应在客户端或服务器模式下握手,等等)。 一旦握手已经开始,但是,任何新设置(客户端/服务器模式除外,见下文)将被用于下一次握手。 - 初始握手 - 初始握手是两个对等体交换通信参数直到建立SSLSession的过程。 在此阶段不能发送应用程序数据。
- 应用数据 - 一旦建立了通信参数并且握手完成,应用程序数据可能会流经
SSLEngine
。 出站应用程序消息被加密和完整性保护,入站消息反过来。 - 重新握手 - 任一方都可以在应用程序数据阶段的任何时间请求重新协商会话。 新的握手数据可以在应用程序数据之间混合。 在启动重新执行阶段之前,应用程序可能会重置SSL / TLS / DTLS通信参数,例如启用密码列表,以及是否使用客户端身份验证,但不能在客户端/服务器模式之间更改。 如前所述,一旦握手已经开始,任何新的
SSLEngine
配置设置将不会被使用,直到下一次握手。 - 关闭 - 当不再需要连接时,应用程序应关闭
SSLEngine
并在关闭底层传输机制之前发送/接收剩余的消息给对等体。 一旦发动机关闭,它不可重复使用:必须创建一个新的SSLEngine
。
SSLEngine
通过调用创建SSLContext.createSSLEngine()
从初始化SSLContext
。 任何配置参数应使得在第一次调用之前设置wrap()
,unwrap()
,或beginHandshake()
。 这些方法都触发初始握手。数据通过引擎分别通过呼叫
wrap()
或unwrap()
来查询出站或入站数据。 根据SSLEngine
的状态,wrap()
调用可能会从源缓冲区消耗应用程序数据,并可能在目标缓冲区中产生网络数据。 出站数据可能包含应用程序和/或握手数据。 调用unwrap()
将检查源缓冲区,如果数据是握手信息,则可以提前握手,如果数据是应用程序,则可以将应用程序数据放置在目标缓冲区中。 底层SSL / TLS / DTLS算法的状态将决定何时消耗和生成数据。致电
wrap()
和unwrap()
返回一个SSLEngineResult
,指示操作的状态,以及(可选)如何与引擎进行交互以取得进展。SSLEngine
生成/消耗完整的SSL / TLS / DTLS数据包,并且在内部调用wrap()/unwrap()
之间不存储应用程序数据。 因此,输入和输出ByteBuffer
必须适当地确定大小以保存可以生成的最大记录。 应调用SSLSession.getPacketBufferSize()
和SSLSession.getApplicationBufferSize()
来确定适当的缓冲区大小。 出站应用程序数据缓冲区的大小通常没有关系。 如果缓冲区条件不允许正确消耗/生成数据,则应用程序必须确定(通过SSLEngineResult
)并更正问题,然后重新尝试该呼叫。例如,如果引擎确定没有足够的目标缓冲区可用,
unwrap()
将返回SSLEngineResult.Status.BUFFER_OVERFLOW
结果。 应用程序应调用SSLSession.getApplicationBufferSize()
,并将该值与目标缓冲区中的可用空间进行比较,如有必要,放大缓冲区。 同样地,如果unwrap()
要返回一个SSLEngineResult.Status.BUFFER_UNDERFLOW
,那么应用程序应该调用SSLSession.getPacketBufferSize()
来确保源缓冲区有足够的空间保存一个记录(如有必要放大),然后获取更多的入站数据。SSLEngineResult r = engine.unwrap(src, dst); switch (r.getStatus()) { BUFFER_OVERFLOW: // Could attempt to drain the dst buffer of any already obtained // data, but we'll just increase it to the size needed. int appSize = engine.getSession().getApplicationBufferSize(); ByteBuffer b = ByteBuffer.allocate(appSize + dst.position()); dst.flip(); b.put(dst); dst = b; // retry the operation. break; BUFFER_UNDERFLOW: int netSize = engine.getSession().getPacketBufferSize(); // Resize buffer if needed. if (netSize > dst.capacity()) { ByteBuffer b = ByteBuffer.allocate(netSize); src.flip(); b.put(src); src = b; } // Obtain more inbound network data for src, // then retry the operation. break; // other cases: CLOSED, OK. }
与
SSLSocket
不同,SSLEngine的所有方法都是非阻塞的。SSLEngine
实现可能需要可能需要较长时间才能完成或甚至可能阻止的任务的结果。 例如,TrustManager可能需要连接到远程证书验证服务,或者KeyManager可能需要提示用户确定要作为客户端身份验证的一部分使用哪个证书。 另外,创建加密签名并验证它们可能很慢,似乎阻塞。对于可能会阻止的任何操作,
SSLEngine
将创建一个Runnable
委托任务。 当SSLEngineResult
指出需要委派的任务结果时,应用程序必须调用getDelegatedTask()
获取未完成的委托任务,并调用其run()
方法(可能根据计算策略使用不同的线程)。 应用程序应继续获取委托任务,直到不再存在,并再次尝试原始操作。在通信会话结束时,应用程序应正确关闭SSL / TLS / DTLS链路。 SSL / TLS / DTLS协议具有闭合握手消息,并且在释放
SSLEngine
并关闭底层传输机制之前,应将这些消息传达给对等体。 关闭可以由以下之一启动:SSLException,入站关闭握手消息或其中一种关闭方法。 在所有情况下,由发动机产生的关闭握手报文,并wrap()
直至所得应被重复调用SSLEngineResult
‘封闭’的状态返回,或isOutboundDone()
返回true。 从wrap()
方法获取的所有数据都应发送给对等体。closeOutbound()
用于向引擎发信号通知应用程序将不再发送任何数据。通过发送自己的关闭握手消息,对等体将通知其意图关闭。 在通过本地
SSLEngine
的unwrap()
呼叫收到并处理此消息后,应用程序可以通过调用unwrap()
并查找状态为“CLOSED”的SSLEngineResult
来检测关闭,或者如果isInboundDone()
返回true。 如果由于某种原因,对等体在没有发送适当的SSL / TLS / DTLS关闭消息的情况下关闭通信链路,则应用程序可以检测流终端,并可以通过closeInbound()
向引擎发信号通知 ,将不再有入站消息被处理。 某些应用程序可能选择要求从对等体定期关闭消息,在这种情况下,它们可以检查闭包是由握手消息生成的,而不是流出尾流条件。有两组密码套件,您需要知道何时管理密码套件:
- 支持的密码套件:SSL实现支持的所有套件。 此列表使用
getSupportedCipherSuites()
报告。 - 启用的密码套件可能少于全套支持的套件。 该组使用
setEnabledCipherSuites(String [])
方法设置,并使用getEnabledCipherSuites()
方法进行查询。 最初,将在启动最小建议配置的新引擎上启用一组默认密码套件。
每个SSL / TLS / DTLS连接必须有一个客户端和一个服务器,因此每个端点必须决定要承担哪个角色。 这个选择决定了谁开始握手过程以及每一方应该发送哪种类型的消息。 方法
setUseClientMode(boolean)
配置该模式。 一旦初始握手开始,即使执行重新协商,SSLEngine
也无法在客户端和服务器模式之间切换。应用程序可能会选择在不同的线程中处理委托的任务。 当
SSLEngine
创建,目前AccessControlContext
被保存。 将使用此上下文处理所有未来的委托任务:即,所有访问控制决定将使用在引擎创建时捕获的上下文进行。
并发注意事项 :有两个并发问题需要注意:-
wrap()
和unwrap()
方法可以彼此并发执行。 - SSL / TLS / DTLS协议采用有序数据包。 应用程序必须注意确保生成的数据包按顺序传递。 如果数据包无序到达,可能会发生意外或致命的结果。
例如:
synchronized (outboundLock) { sslEngine.wrap(src, dst); outboundQueue.put(dst); }
作为推论,两个线程不能同时尝试调用相同的方法(wrap()
或unwrap()
),因为无法保证最终的数据包顺序。
- 从以下版本开始:
- 1.5
- 另请参见:
-
SSLContext
,SSLSocket
,SSLServerSocket
,SSLSession
,Socket
-
-
方法摘要
所有方法 接口方法 抽象方法 具体的方法 Modifier and Type 方法 描述 abstract void
beginHandshake()
在这个SSLEngine上启动握手(初始或重新协商)。abstract void
closeInbound()
表示不会将更多入站网络数据发送到此SSLEngine
。abstract void
closeOutbound()
表示在此SSLEngine
不会再发送外部应用程序数据。String
getApplicationProtocol()
返回为此连接协商的最新应用程序协议值。abstract Runnable
getDelegatedTask()
返回此SSLEngine
的委托Runnable
任务。abstract String[]
getEnabledCipherSuites()
返回当前启用此引擎使用的SSL密码套件的名称。abstract String[]
getEnabledProtocols()
返回当前启用此协议版本的协议版本的名称,以使用此SSLEngine
。abstract boolean
getEnableSessionCreation()
如果此引擎可能建立新的SSL会话,则返回true。String
getHandshakeApplicationProtocol()
返回当前正在进行的SSL / TLS握手协商的应用协议值。BiFunction<SSLEngine,List<String>,String>
getHandshakeApplicationProtocolSelector()
检索在SSL / TLS / DTLS握手期间选择应用协议值的回调函数。SSLSession
getHandshakeSession()
返回在SSL / TLS / DTLS握手期间构建的SSLSession
。abstract SSLEngineResult.HandshakeStatus
getHandshakeStatus()
返回此SSLEngine
的当前握手状态。abstract boolean
getNeedClientAuth()
如果引擎 需要客户端验证,则返回true。String
getPeerHost()
返回对等体的主机名。int
getPeerPort()
返回对端的端口号。abstract SSLSession
getSession()
返回此SSLSession
中使用的SSLEngine
。SSLParameters
getSSLParameters()
返回此SSLEngine有效的SSLParameters。abstract String[]
getSupportedCipherSuites()
返回可以在此引擎上使用的密码套件的名称。abstract String[]
getSupportedProtocols()
返回可与此SSLEngine
一起使用的协议的名称。abstract boolean
getUseClientMode()
如果在握手时将引擎设置为使用客户端模式,则返回true。abstract boolean
getWantClientAuth()
如果引擎将 请求客户端身份验证,则返回true。abstract boolean
isInboundDone()
返回unwrap(ByteBuffer, ByteBuffer)
是否接受任何更多的入站数据消息。abstract boolean
isOutboundDone()
返回wrap(ByteBuffer, ByteBuffer)
是否会产生更多的出站数据消息。abstract void
setEnabledCipherSuites(String[] suites)
设置启用此引擎使用的密码套件。abstract void
setEnabledProtocols(String[] protocols)
设置允许在此引擎上使用的协议版本。abstract void
setEnableSessionCreation(boolean flag)
控制此引擎是否可以建立新的SSL会话。void
setHandshakeApplicationProtocolSelector(BiFunction<SSLEngine,List<String>,String> selector)
注册回调函数,为SSL / TLS / DTLS握手选择应用程序协议值。abstract void
setNeedClientAuth(boolean need)
配置引擎 要求客户端认证。void
setSSLParameters(SSLParameters params)
将SSLParameters应用于此引擎。abstract void
setUseClientMode(boolean mode)
配置引擎在握手时使用客户端(或服务器)模式。abstract void
setWantClientAuth(boolean want)
配置引擎以 请求客户端身份验证。SSLEngineResult
unwrap(ByteBuffer src, ByteBuffer dst)
尝试将SSL / TLS / DTLS网络数据解码为明文应用数据缓冲区。SSLEngineResult
unwrap(ByteBuffer src, ByteBuffer[] dsts)
尝试将SSL / TLS / DTLS网络数据解码为一系列明文应用程序数据缓冲区。abstract SSLEngineResult
unwrap(ByteBuffer src, ByteBuffer[] dsts, int offset, int length)
尝试将SSL / TLS / DTLS网络数据解码为明文应用程序数据缓冲区的子序列。abstract SSLEngineResult
wrap(ByteBuffer[] srcs, int offset, int length, ByteBuffer dst)
尝试将明文字节从数据缓冲区的子序列编码为SSL / TLS / DTLS网络数据。SSLEngineResult
wrap(ByteBuffer[] srcs, ByteBuffer dst)
尝试将明文字节从一系列数据缓冲区编码为SSL / TLS / DTLS网络数据。SSLEngineResult
wrap(ByteBuffer src, ByteBuffer dst)
尝试将明文应用程序数据的缓冲区编码到SSL / TLS / DTLS网络数据中。
-
-
-
构造方法详细信息
-
SSLEngine
protected SSLEngine()
SSLEngine
构造方法不提供内部会话重用策略的提示。
-
SSLEngine
protected SSLEngine(String peerHost, int peerPort)
构造函数为SSLEngine
。SSLEngine
实现可以使用peerHost
和peerPort
参数作为其内部会话重用策略的提示。某些密码套件(如Kerberos)需要远程主机名信息。 这个类的实现应该使用这个构造函数来使用Kerberos。
参数未通过
SSLEngine
认证。- 参数
-
peerHost
- 对等主机的名称 -
peerPort
- 对等端口号 - 另请参见:
-
SSLContext.createSSLEngine(String, int)
,SSLSessionContext
-
-
方法详细信息
-
getPeerHost
public String getPeerHost()
返回对等体的主机名。请注意,该值未通过身份验证,不应被依赖。
- 结果
- 对等体的主机名,如果没有可用,则为null。
-
getPeerPort
public int getPeerPort()
返回对端的端口号。请注意,该值未通过身份验证,不应被依赖。
- 结果
- 对端的端口号,如果没有可用,则为-1。
-
wrap
public SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException
尝试将明文应用程序数据的缓冲区编码到SSL / TLS / DTLS网络数据中。调用此方法的行为方式与调用的方式完全相同:
engine.wrap(new ByteBuffer [] { src }, 0, 1, dst);
- 参数
-
src
- 一个包含出站应用程序数据的ByteBuffer
-
dst
- 一个ByteBuffer
来保存出站网络数据 - 结果
-
一个
SSLEngineResult
描述了这个操作的结果。 - 异常
-
SSLException
- 处理导致SSLEngine
中断的数据时遇到问题。 有关发动机关闭的更多信息,请参阅课堂说明。 -
ReadOnlyBufferException
- 如果dst
缓冲区是只读的。 -
IllegalArgumentException
- 如果src
或dst
为null。 -
IllegalStateException
- 如果客户端/服务器模式尚未设置。 - 另请参见:
-
wrap(ByteBuffer [], int, int, ByteBuffer)
-
wrap
public SSLEngineResult wrap(ByteBuffer[] srcs, ByteBuffer dst) throws SSLException
尝试将明文字节从一系列数据缓冲区编码为SSL / TLS / DTLS网络数据。调用此方法的行为方式与调用的方式完全相同:
engine.wrap(srcs, 0, srcs.length, dst);
- 参数
-
srcs
- 包含出站应用程序数据的ByteBuffers
数组 -
dst
- 一个ByteBuffer
来保存出站网络数据 - 结果
-
一个
SSLEngineResult
描述了这个操作的结果。 - 异常
-
SSLException
- 处理导致SSLEngine
中断的数据时遇到问题。 有关发动机关闭的更多信息,请参阅课堂说明。 -
ReadOnlyBufferException
- 如果dst
缓冲区是只读的。 -
IllegalArgumentException
- 如果srcs
或dst
为空,或者srcs
任何元素为空。 -
IllegalStateException
- 如果客户端/服务器模式尚未设置。 - 另请参见:
-
wrap(ByteBuffer [], int, int, ByteBuffer)
-
wrap
public abstract SSLEngineResult wrap(ByteBuffer[] srcs, int offset, int length, ByteBuffer dst) throws SSLException
尝试将明文字节从数据缓冲区的子序列编码为SSL / TLS / DTLS网络数据。 这种“收集”操作在单个调用中编码来自一个或多个给定的缓冲器序列的字节序列。 在实现网络协议或文件格式时,收集包裹通常很有用,例如,将数据分组成由一个或多个固定长度的标头以及可变长度的主体组成的段。 见GatheringByteChannel
有关收集更多信息,并GatheringByteChannel.write(ByteBuffer[], int, int)
对序列行为的更多信息。根据SSLEngine的状态,此方法可能会产生网络数据,而不会消耗任何应用程序数据(例如,它可能会产生握手数据)。
应用程序负责将网络数据可靠地传输到对等体,并确保通过多次调用wrap()创建的数据按照生成的顺序进行传输。 应用程序必须正确同步多个调用此方法。
如果这个
SSLEngine
尚未开始初始握手,这种方法会自动开始握手。此方法将尝试生成SSL / TLS / DTLS记录,并且将尽可能消耗尽可能多的源数据,但绝对不会消耗每个缓冲区中剩余字节的总和。 每个
ByteBuffer
的位置被更新以反映消耗或生成的数据量。 极限保持不变。srcs
和dst ByteBuffer
使用的底层内存不能相同。有关发动机关闭的更多信息,请参阅课堂说明。
- 参数
-
srcs
- 包含出站应用程序数据的ByteBuffers
数组 -
offset
- 要从中检索字节的第一个缓冲区的缓冲区数组中的偏移量; 它必须是非负数,不大于srcs.length
-
length
- 要访问的缓冲区的最大数量; 它必须是非负数,不大于srcs.length
-offset
-
dst
- 一个ByteBuffer
来保存出站网络数据 - 结果
-
一个
SSLEngineResult
描述了这个操作的结果。 - 异常
-
SSLException
- 处理导致SSLEngine
中断的数据时遇到问题。 有关发动机关闭的更多信息,请参阅课堂说明。 -
IndexOutOfBoundsException
- 如果offset
和length
参数的前提条件不成立。 -
ReadOnlyBufferException
- 如果dst
缓冲区是只读的。 -
IllegalArgumentException
- 如果srcs
或dst
为空,或者指定的srcs
序列中的任何元素为空。 -
IllegalStateException
- 如果客户端/服务器模式尚未设置。 - 另请参见:
-
GatheringByteChannel
,GatheringByteChannel.write( ByteBuffer[], int, int)
-
unwrap
public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst) throws SSLException
尝试将SSL / TLS / DTLS网络数据解码为明文应用数据缓冲区。调用此方法的行为方式与调用的方式完全相同:
engine.unwrap(src, new ByteBuffer [] { dst }, 0, 1);
- 参数
-
src
- 包含入站网络数据的ByteBuffer
。 -
dst
- 一个ByteBuffer
保存入站应用程序数据。 - 结果
-
一个描述此操作结果的
SSLEngineResult
。 - 异常
-
SSLException
- 处理导致SSLEngine
中断的数据时遇到问题。 有关发动机关闭的更多信息,请参阅课堂说明。 -
ReadOnlyBufferException
- 如果dst
缓冲区是只读的。 -
IllegalArgumentException
- 如果src
或dst
为空。 -
IllegalStateException
- 如果客户端/服务器模式尚未设置。 - 另请参见:
-
unwrap(ByteBuffer, ByteBuffer [], int, int)
-
unwrap
public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts) throws SSLException
尝试将SSL / TLS / DTLS网络数据解码为一系列明文应用程序数据缓冲区。调用此方法的行为方式与调用的方式完全相同:
engine.unwrap(src, dsts, 0, dsts.length);
- 参数
-
src
- 一个包含入站网络数据的ByteBuffer
。 -
dsts
-的阵列ByteBuffer
s至保持入站应用程序数据。 - 结果
-
一个
SSLEngineResult
描述了这个操作的结果。 - 异常
-
SSLException
- 处理导致SSLEngine
中止的数据时遇到问题。 有关发动机关闭的更多信息,请参阅课堂说明。 -
ReadOnlyBufferException
- 如果任何一个dst
缓冲区是只读的。 -
IllegalArgumentException
- 如果src
或dsts
为空,或者dsts
任何元素为空。 -
IllegalStateException
- 如果客户端/服务器模式尚未设置。 - 另请参见:
-
unwrap(ByteBuffer, ByteBuffer [], int, int)
-
unwrap
public abstract SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts, int offset, int length) throws SSLException
尝试将SSL / TLS / DTLS网络数据解码为明文应用程序数据缓冲区的子序列。 这种“散射”操作在单次调用中将字节序列解码为给定的缓冲器序列中的一个或多个。 当实现网络协议或文件格式时,散射展开通常很有用,例如,将数据分组成由一个或多个固定长度的标题后跟可变长度的主体组成的段。 见ScatteringByteChannel
关于分散的更多信息,并ScatteringByteChannel.read(ByteBuffer[], int, int)
对序列行为的更多信息。根据SSLEngine的状态,此方法可能会消耗网络数据,而不会生成任何应用程序数据(例如,它可能会消耗握手数据)。
该应用程序负责从对等方可靠地获取网络数据,并按照收到的顺序调用unwrap()。 应用程序必须正确同步多个调用此方法。
如果这个
SSLEngine
还没有开始初始握手,这个方法会自动开始握手。此方法将尝试使用一个完整的SSL / TLS / DTLS网络数据包,但绝对不会消耗大于缓冲区中剩余字节的总和。 每个
ByteBuffer
的位置被更新以反映消耗或产生的数据量。 极限保持不变。src
和dsts ByteBuffer
使用的底层内存不能相同。作为此呼叫的结果,可能会修改入站网络缓冲区:因此,如果网络数据包需要某些次要目的,则在调用此方法之前应重复数据。 注意:网络数据对第二个SSLEngine不会有用,因为每个SSLEngine都包含影响SSL / TLS / DTLS消息的唯一随机状态。
有关发动机关闭的更多信息,请参阅课堂说明。
- 参数
-
src
- 包含入站网络数据的ByteBuffer
。 -
dsts
-的阵列ByteBuffer
s至保持入站应用程序数据。 -
offset
- 要传输字节的第一个缓冲区的缓冲区数组中的偏移量; 它必须是非负数,不大于dsts.length
。 -
length
- 要访问的缓冲区的最大数量; 它必须是非负的,不大于dsts.length
-offset
。 - 结果
-
一个
SSLEngineResult
描述了这个操作的结果。 - 异常
-
SSLException
- 处理导致SSLEngine
中断的数据时遇到问题。 有关发动机关闭的更多信息,请参阅课堂说明。 -
IndexOutOfBoundsException
- 如果offset
和length
参数的前提条件不成立。 -
ReadOnlyBufferException
- 如果任何一个dst
缓冲区是只读的。 -
IllegalArgumentException
- 如果src
或dsts
为null,或者如果指定的dsts
序列中的任何元素为空。 -
IllegalStateException
- 如果客户端/服务器模式尚未设置。 - 另请参见:
-
ScatteringByteChannel
,ScatteringByteChannel.read( ByteBuffer[], int, int)
-
getDelegatedTask
public abstract Runnable getDelegatedTask()
返回此SSLEngine
的委托Runnable
任务。SSLEngine
操作可能需要阻止或可能需要较长时间才能完成的操作结果。 该方法用于获得一个突出的Runnable
操作(任务)。 每个任务必须分配一个线程(可能是当前的)来执行run
操作。 一旦run
方法返回,Runnable
对象不再需要,可能会被丢弃。创建此对象时,委派的任务在
AccessControlContext
中运行。调用此方法将返回每个未完成的任务一次。
多个委托任务可以并行运行。
- 结果
-
委托
Runnable
任务,如果没有可用,Runnable
null。
-
closeInbound
public abstract void closeInbound() throws SSLException
表示没有更多的入站网络数据将发送到此SSLEngine
。如果应用程序通过调用
closeOutbound()
启动了关闭过程,在某些情况下,不要求发起方等待对等体的相应的关闭消息。 (有关等待关闭警报的详细信息,请参阅TLS规范( RFC 2246 )的7.2.1节。)在这种情况下,不需要调用此方法。但是如果应用程序没有启动关闭过程,或者如果上述情况不适用,则只要达到SSL / TLS / DTLS数据流的结尾,就应该调用此方法。 这确保入站端的关闭,并检查对等体是否正确遵循SSL / TLS / DTLS关闭过程,从而检测可能的截断攻击。
该方法是幂等的:如果入站端已经关闭,则此方法不执行任何操作。
应该调用
wrap()
刷新剩余的握手数据。- 异常
-
SSLException
- 如果此引擎尚未从对等体收到正确的SSL / TLS / DTLS关闭通知消息。 - 另请参见:
-
isInboundDone()
,isOutboundDone()
-
isInboundDone
public abstract boolean isInboundDone()
返回unwrap(ByteBuffer, ByteBuffer)
是否接受任何更多的入站数据消息。- 结果
-
如果
SSLEngine
不再消耗网络数据(并且暗示不会产生任何更多的应用程序数据),SSLEngine
true。 - 另请参见:
-
closeInbound()
-
closeOutbound
public abstract void closeOutbound()
表示在这个SSLEngine
没有更多出站的应用程序数据将被发送。这个方法是幂等的:如果出站方已经关闭了,这个方法什么都不做。
应调用
wrap(ByteBuffer, ByteBuffer)
刷新剩余的握手数据。- 另请参见:
-
isOutboundDone()
-
isOutboundDone
public abstract boolean isOutboundDone()
返回wrap(ByteBuffer, ByteBuffer)
是否会产生任何更多的出站数据消息。请注意,在关闭阶段,
SSLEngine
可能会产生必须发送给对等体的握手关闭数据。 必须调用wrap()
才能生成此数据。 当此方法返回true时,不会再创建更多的出站数据。- 结果
-
如果
SSLEngine
不会产生任何更多的网络数据,SSLEngine
true - 另请参见:
-
closeOutbound()
,closeInbound()
-
getSupportedCipherSuites
public abstract String[] getSupportedCipherSuites()
返回可以在此引擎上使用的密码套件的名称。 通常,默认情况下实际上只能启用这些子集,因为此列表可能包括不符合这些默认值的服务质量要求的密码套件。 这样的密码套件在专门的应用中可能是有用的。返回的阵列包括来自Java加密体系结构标准算法名称文档的JSSE Cipher Suite Names部分中的标准加密套件名称的密码套件,还可以包括提供商支持的其他密码套件。
- 结果
- 一组加密套件名称
- 另请参见:
-
getEnabledCipherSuites()
,setEnabledCipherSuites(String [])
-
getEnabledCipherSuites
public abstract String[] getEnabledCipherSuites()
返回当前启用此引擎使用的SSL密码套件的名称。 当首次创建SSLEngine时,所有启用的密码套件都支持最低服务质量。 因此,在某些环境中,此值可能为空。请注意,即使启用套件,也可能永远不会使用。 如果对等体不支持,或者其使用受到限制,或者该套件的必需证书(和私钥)不可用,或者启用匿名套件但需要验证,则可能会发生这种情况。
返回的数组包括来自Java加密体系结构标准算法名称文档的JSSE Cipher Suite Names部分的标准密码套件名称列表中的密码套件,还可以包括提供商支持的其他密码套件。
- 结果
- 一组加密套件名称
- 另请参见:
-
getSupportedCipherSuites()
,setEnabledCipherSuites(String [])
-
setEnabledCipherSuites
public abstract void setEnabledCipherSuites(String[] suites)
设置启用此引擎使用的密码套件。suites
参数中的每个加密套件都必须由getSupportedCipherSuites()列出,否则该方法将失败。 成功调用此方法后,只能启用suites
参数中列出的suites
。请注意,密码套件名称的标准列表可以在Java加密体系结构标准算法名称文档的JSSE Cipher Suite Names部分找到。 提供者可能会支持此列表中找不到的密码套件名称,也可能不会使用某个密码套件的推荐名称。
有关为什么特定加密套件可能永远不会在引擎上使用的详细信息,请参阅
getEnabledCipherSuites()
。- 参数
-
suites
- 启用所有密码套件的名称 - 异常
-
IllegalArgumentException
- 当不支持由参数命名的一个或多个密码时,或当参数为空时。 - 另请参见:
-
getSupportedCipherSuites()
,getEnabledCipherSuites()
-
getSupportedProtocols
public abstract String[] getSupportedProtocols()
返回可与此SSLEngine
一起使用的协议的名称。- 结果
- 支持的一系列协议
-
getEnabledProtocols
public abstract String[] getEnabledProtocols()
返回当前启用此协议版本的协议版本的名称,用于此SSLEngine
。请注意,即使启用协议,也可能永远不会使用该协议。 如果对等体不支持协议或者限制使用协议,或协议没有启用密码套件,则可能会发生这种情况。
- 结果
- 一系列协议
- 另请参见:
-
setEnabledProtocols(String [])
-
setEnabledProtocols
public abstract void setEnabledProtocols(String[] protocols)
设置允许在此引擎上使用的协议版本。协议必须被getSupportedProtocols()列为受支持。 成功调用此方法后,只有
protocols
参数中列出的协议才能使用。- 参数
-
protocols
- 启用的所有协议的名称。 - 异常
-
IllegalArgumentException
- 当一个或多个由参数命名的协议不受支持或协议参数为null时。 - 另请参见:
-
getEnabledProtocols()
-
getSession
public abstract SSLSession getSession()
返回此SSLSession
中使用的SSLEngine
。这些可以长期存在,并且经常对应于一些用户的整个登录会话。 会话指定了该会话中所有连接正在主动使用的特定加密套件,以及会话的客户端和服务器的身份。
与
SSLSocket.getSession()
不同,这种方法不会阻止,直到握手完成。在初始握手完成之前,此方法返回一个报告“SSL_NULL_WITH_NULL_NULL”无效加密套件的会话对象。
- 结果
-
该
SSLSession
为这SSLEngine
- 另请参见:
-
SSLSession
-
getHandshakeSession
public SSLSession getHandshakeSession()
返回在SSL / TLS / DTLS握手期间构建的SSLSession
。TLS / DTLS协议可以协商使用此类实例时所需的参数,但在
SSLSession
完全初始化并通过getSession
可用之前可以getSession
。 例如,有效的签名算法列表可能限制在TrustManager决策期间可以使用的证书的类型,或者可以调整最大TLS / DTLS分段数据包大小以更好地支持网络环境。这种方法可以及早访问正在建造的
SSLSession
。 取决于握手进度有多远,有些数据可能尚未被使用。 例如,如果远程服务器将发送一个证书链,但链尚未没有被处理,则getPeerCertificates
的方法SSLSession
将抛出SSLPeerUnverifiedException。 一旦该链已被处理,getPeerCertificates
将返回正确的值。- 结果
-
如果此实例当前不是握手,或者当前握手尚未进展到足以创建基本SSLSession,则为null。
否则,此方法返回目前正在协商的
SSLSession
。 - 异常
-
UnsupportedOperationException
- 如果底层提供程序未实现该操作。 - 从以下版本开始:
- 1.7
- 另请参见:
-
SSLSocket
,SSLSession
,ExtendedSSLSession
,X509ExtendedKeyManager
,X509ExtendedTrustManager
-
beginHandshake
public abstract void beginHandshake() throws SSLException
在这个SSLEngine上启动握手(初始或重新协商)。初始握手不需要这种方法,因为如果尚未开始握手,那么
wrap()
和unwrap()
方法将隐含地称之为该方法。请注意,对等体还可以通过发送适当的会话重新协商握手消息来请求与该
SSLEngine
的会话重新协商。与
SSLSocket#startHandshake()
方法不同,此方法在握手完成之前不会阻止。要强制完成SSL / TLS / DTLS会话重新协商,在调用此方法之前,当前会话应该被无效。
某些协议可能不支持现有引擎上的多次握手,并可能会导致
SSLException
。- 异常
-
SSLException
- 如果在发信号SSLEngine
开始新的握手时遇到问题。 有关发动机关闭的更多信息,请参阅课堂说明。 -
IllegalStateException
- 如果客户端/服务器模式尚未设置。 - 另请参见:
-
SSLSession.invalidate()
-
getHandshakeStatus
public abstract SSLEngineResult.HandshakeStatus getHandshakeStatus()
返回此SSLEngine
的当前握手状态。- 结果
-
目前
SSLEngineResult.HandshakeStatus
。
-
setUseClientMode
public abstract void setUseClientMode(boolean mode)
配置引擎在握手时使用客户端(或服务器)模式。在发生任何握手之前必须调用此方法。 一旦握手已经开始,在该引擎的使用寿命内不能重置该模式。
服务器通常认证自己,客户端不需要这样做。
- 参数
-
mode
- 如果引擎应该以“客户端”模式开始握手,mode
true - 异常
-
IllegalArgumentException
- 如果在初始握手开始后尝试模式更改。 - 另请参见:
-
getUseClientMode()
-
getUseClientMode
public abstract boolean getUseClientMode()
如果在握手时将引擎设置为使用客户端模式,则返回true。- 结果
- 如果引擎应该在“客户端”模式下进行握手,则为真
- 另请参见:
-
setUseClientMode(boolean)
-
setNeedClientAuth
public abstract void setNeedClientAuth(boolean need)
配置引擎要求客户端认证。 此选项仅对服务器模式下的引擎有用。引擎的客户端验证设置是以下之一:
- 需要客户端验证
- 客户端认证请求
- 不需要客户端认证
与
setWantClientAuth(boolean)
不同,如果设置此选项,并且客户端选择不提供有关其自身的身份验证信息, 则协商将停止,并且引擎将开始其关闭过程 。调用此方法将覆盖此方法或
setWantClientAuth(boolean)
所做的任何以前的设置。- 参数
-
need
- 如果需要客户端验证,则设置为true;如果不需要客户端验证,则设置为false。 - 另请参见:
-
getNeedClientAuth()
,setWantClientAuth(boolean)
,getWantClientAuth()
,setUseClientMode(boolean)
-
getNeedClientAuth
public abstract boolean getNeedClientAuth()
如果引擎需要客户端验证,则返回true。 此选项仅对服务器模式下的引擎有用。- 结果
- 如果需要客户端验证,则为true;如果不需要客户端验证,则为false。
- 另请参见:
-
setNeedClientAuth(boolean)
,setWantClientAuth(boolean)
,getWantClientAuth()
,setUseClientMode(boolean)
-
setWantClientAuth
public abstract void setWantClientAuth(boolean want)
配置引擎以请求客户端身份验证。 此选项仅对服务器模式下的引擎有用。引擎的客户端验证设置是以下之一:
- 需要客户端验证
- 客户端认证请求
- 不需要客户端认证
与
setNeedClientAuth(boolean)
不同,如果设置了此选项,并且客户端选择不提供有关其自身的身份验证信息, 协商将继续 。调用此方法将覆盖此方法或
setNeedClientAuth(boolean)
所做的任何以前的设置。- 参数
-
want
- 如果请求客户端认证,则设置为true;如果不需要客户端认证,则设置为false。 - 另请参见:
-
getWantClientAuth()
,setNeedClientAuth(boolean)
,getNeedClientAuth()
,setUseClientMode(boolean)
-
getWantClientAuth
public abstract boolean getWantClientAuth()
如果引擎将请求客户端身份验证,则返回true。 此选项仅对服务器模式下的引擎有用。- 结果
- 如果客户端认证被请求,则为true;如果不需要客户端认证,则为false。
- 另请参见:
-
setNeedClientAuth(boolean)
,getNeedClientAuth()
,setWantClientAuth(boolean)
,setUseClientMode(boolean)
-
setEnableSessionCreation
public abstract void setEnableSessionCreation(boolean flag)
控制此引擎是否可以建立新的SSL会话。 如果不允许会话创建,并且没有现有的会话恢复,则不会有成功的握手。- 参数
-
flag
- true表示可以创建会话; 这是默认值。 false表示必须恢复现有会话 - 另请参见:
-
getEnableSessionCreation()
-
getEnableSessionCreation
public abstract boolean getEnableSessionCreation()
如果此引擎可能建立新的SSL会话,则返回true。- 结果
- true表示可以创建会话; 这是默认值。 false表示必须恢复现有会话
- 另请参见:
-
setEnableSessionCreation(boolean)
-
getSSLParameters
public SSLParameters getSSLParameters()
返回此SSLEngine有效的SSLParameters。 返回的SSLParameters的密码和协议始终不为空。- 结果
- 此SSLEngine的SSLParameters有效。
- 从以下版本开始:
- 1.6
-
setSSLParameters
public void setSSLParameters(SSLParameters params)
将SSLParameters应用于此引擎。意即:
- 如果
params.getCipherSuites()
为非空值,则使用该值调用setEnabledCipherSuites()
。 - 如果
params.getProtocols()
为非空值,则使用该值调用setEnabledProtocols()
。 - 如果
params.getNeedClientAuth()
或params.getWantClientAuth()
返回true
,分别调用setNeedClientAuth(true)
和setWantClientAuth(true)
; 否则setWantClientAuth(false)
被调用。 - 如果
params.getServerNames()
为非空值,引擎将使用该值配置其服务器名称。 - 如果
params.getSNIMatchers()
不为空,引擎将使用该值配置其SNI匹配器。
- 参数
-
params
- 参数 - 异常
-
IllegalArgumentException
- 如果setEnabledCipherSuites()或setEnabledProtocols()调用失败 - 从以下版本开始:
- 1.6
- 如果
-
getApplicationProtocol
public String getApplicationProtocol()
返回为此连接协商的最新应用程序协议值。如果基础SSL / TLS / DTLS实现支持,应用程序名称协商机制(如应用层协议协商(ALPN)) RFC 7301可以协商对等体之间的应用级别值。
- 实现要求:
-
此类中的实现抛出
UnsupportedOperationException
并且不执行其他操作。 - 结果
-
如果尚未确定应用程序协议是否可用于此连接,
String
空,如果应用协议值不被使用String
空String
如果成功协商值,String
空的应用协议String
。 - 异常
-
UnsupportedOperationException
- 如果底层提供程序未实现该操作。 - 从以下版本开始:
- 9
-
getHandshakeApplicationProtocol
public String getHandshakeApplicationProtocol()
返回当前正在进行的SSL / TLS握手协商的应用协议值。像
getHandshakeSession()
一样,连接可能在握手的中间。 应用协议可能已经或可能还没有可用。- 实现要求:
-
此类中的实现将抛出
UnsupportedOperationException
并且不执行其他操作。 - 结果
-
如果尚未确定应用程序协议是否可用于此握手,
String
空,如果应用协议值不被使用String
空String
如果成功协商值,String
空的应用协议String
。 - 异常
-
UnsupportedOperationException
- 如果底层提供程序未实现该操作。 - 从以下版本开始:
- 9
-
setHandshakeApplicationProtocolSelector
public void setHandshakeApplicationProtocolSelector(BiFunction<SSLEngine,List<String>,String> selector)
注册回调函数,为SSL / TLS / DTLS握手选择应用程序协议值。 该函数将覆盖使用SSLParameters.setApplicationProtocols
提供的任何值,并且它支持以下类型参数:-
SSLEngine
-
The function's first argument allows the current
SSLEngine
to be inspected, including the handshake session and configuration settings. -
List<String>
- The function's second argument lists the application protocol names advertised by the TLS peer.
-
String
-
The function's result is an application protocol name, or null to indicate that none of the advertised names are acceptable. If the return value is an empty
String
then application protocol indications will not be used. If the return value is null (no value chosen) or is a value that was not advertised by the peer, the underlying protocol will determine what action to take. (For example, ALPN will send a "no_application_protocol" alert and terminate the connection.)
serverEngine.setHandshakeApplicationProtocolSelector( (serverEngine, clientProtocols) -> { SSLSession session = serverEngine.getHandshakeSession(); return chooseApplicationProtocol( serverEngine, clientProtocols, session.getProtocol(), session.getCipherSuite()); });
- API Note:
-
在TLS握手开始之前,此方法应由TLS服务器应用程序调用。
此外,该
SSLEngine
应配置与回调函数选择的应用程序协议兼容的参数。 例如,使密码套件选择不佳可能导致没有合适的应用协议。 见SSLParameters
。 - 实现要求:
-
此类中的实现会抛出
UnsupportedOperationException
并且不执行其他操作。 - 参数
-
selector
- 回调函数,或null以禁用回调功能。 - 异常
-
UnsupportedOperationException
- 如果底层提供程序未实现该操作。 - 从以下版本开始:
- 9
-
-
getHandshakeApplicationProtocolSelector
public BiFunction<SSLEngine,List<String>,String> getHandshakeApplicationProtocolSelector()
检索在SSL / TLS / DTLS握手期间选择应用协议值的回调函数。 有关函数的类型参数,请参见setHandshakeApplicationProtocolSelector
。- 实现要求:
-
此类中的实现会抛出
UnsupportedOperationException
并且不执行其他操作。 - 结果
- 回调函数,如果没有设置则返回null。
- 异常
-
UnsupportedOperationException
- 如果底层提供程序不实现该操作。 - 从以下版本开始:
- 9
-
-