【问题标题】:How SSLContext.getInstance() method works?SSLContext.getInstance() 方法如何工作?
【发布时间】:2013-09-17 14:15:55
【问题描述】:

整个代码非常复杂,所以我直接进入重点。 代码如下

SSLContext ctx = SSLContext.getInstance("TLS");

如果您阅读 docs 的 getInstance(String protocol) 方法,它会说

This method traverses the list of registered security Providers, starting
with the most preferred Provider. A new SSLContext object encapsulating
the SSLContextSpi implementation from the first Provider that supports the
specified protocol is returned.

Note that the list of registered providers may be retrieved via the
Security.getProviders() method.

对我来说,Security.getProviders() 方法提供以下提供者

现在我已经验证了“TLS”协议在 com.sun.net.ssl.internal.ssl.Provider(索引 2)中并且总是被选中。

但对应的 SSLContextSpi 对象在 Java 6 和 Java 7 中有所不同。在 java 6 中我得到 com.sun.net.ssl.internal.ssl.SSLContextImpl@7bbf68a9 而在 java 7 中我得到 sun.security.ssl.SSLContextImpl$TLS10Context@615ece16。这会产生非常糟糕的影响,因为稍后我创建 SSL 套接字时它们属于不同的类。

那么为什么会这样呢?有解决办法吗?我想要封装在com.sun.net.ssl.internal.ssl.Provider 上下文中的相同com.sun.net.ssl.internal.ssl.SSLContextImpl@7bbf68a9 SSLContextSpi 对象(这两种情况都相同)。

【问题讨论】:

    标签: java sockets ssl


    【解决方案1】:

    这会产生非常糟糕的影响,因为当我稍后创建 SSL 套接字时,它们属于不同的类。

    这不是一个不好的效果。您从公共 API 中的工厂获得的实际类由 JRE 实现决定:这些具体类不是公共 API 的一部分。

    在 Java 6 和 Java 7 之间获得不同的类这一事实并不重要。即使他们有相同的名字,如果将它们相互比较也是没有意义的。

    编辑:

    public int read(byte[] b) 函数在我给它时只读取 1 个字节 长度为 4 的字节数组,我也确认有 4 流中的字节数。

    SSLSocket 在 Java 7 中的行为正确。事实上,它可能表现得更好,因为这个最初的 1 字节读取是由于 BEAST-prevention measure。我将复制并粘贴我自己对该问题的答案,因为您犯了完全相同的错误。


    假设您正在阅读byte[],就像您在另一端写的一样,这是一个典型的 TCP 错误。它实际上并不特定于 SSL/TLS,但也可能发生在 TCP 连接中。

    在 TCP(和 SSL/TLS)中,不能保证读取器的缓冲区将填充与写入器缓冲区中的数据包完全相同的数据包长度。所有 TCP 保证都是按顺序交付的,因此您最终会获得所有数据,但您必须将其视为流。

    这就是为什么使用 TCP 的协议依赖指示符和分隔符来告诉另一端何时停止读取某些消息。

    例如,HTTP 1.1 使用空行来指示标头何时结束,并使用Content-Length 标头告诉接收者期望的实体长度(或分块传输编码)。 SMTP 还在邮件末尾使用换行符和.

    如果您要设计自己的协议,则需要定义一种方式,让接收者知道您定义的有意义的数据单元何时被分隔。当您读取数据时,读取此类指示符并填充您的读取缓冲区,直到您获得您期望的字节数或直到您找到您定义的分隔符。

    【讨论】:

    • 问题是我从对应于 java 7 的类中获得的套接字实现有错误的 I/O 流字节写入 API。
    • 您所说的“故障”是什么意思?为什么问题会来自这个特定的实现?
    • @AniketThakur 这几乎是不可能的,即使是真的也不会仅仅因为版本之间类名的改变而被解释。我建议您发布您遇到的 实际 问题,而不是从这个无关的调查中产生的问题。
    • @EJP public int read(byte[] b) 函数在我给它一个长度为 4 的字节数组时仅读取 1 个字节,而且我已经确认有流中的 4 个字节。
    • 您已确认如何? 流中的数据已加密:您是如何克服这个问题的?而且在任何情况下,都不能保证“read()”填满缓冲区提供所有可用的数据。如果您的代码依赖于该假设,则它是不正确的。期间。
    猜你喜欢
    • 2021-12-02
    • 1970-01-01
    • 2017-02-04
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多