我正在尝试在我当前的项目中使用 SNI 模式,其中客户端启动与服务器的 SSL 连接。我希望我的服务器知道客户端打算连接的主机/服务器名称。该服务器名称由客户端提供。我有一个 ExtendedSSLSession 对象,但由于我使用的是 Java 7,我无法使用 getRequestedServerNames() 方法(在 Java 8 中引入)来实现我正在寻找的确切功能。不幸的是,我目前的情况不允许我升级我的 java 版本。
我想问社区在使用 Java 7 时是否有获取服务器名称的解决方法?
如有任何指导,我将不胜感激。
谢谢!
最佳答案
好吧,JDK 7 和 8 是开源的,所以原则上您可以向后移植必要的新代码并构建您自己的版本(称之为 7.5?)——至少如果您的要求只是停留在 java7 API 而不是/官方 java7 JRE。但是,如果您谈论的是任何大量的运行时系统或应用程序,尤其是业务关键型系统或应用程序,那么支持起来可能会很麻烦。
作为一种解决方法,我认为——但还没有制定出所有的细节——你可以偷偷相当于 SSLSocketFactory.createSocket(Socket,InputStream,boolean) ,也是 java8 中的新内容,根据文档“underneath”出于同样的原因。特别是如果您使用的是“简单”SSLServerSocket
或 SSLSocket(client=false)
接口(interface):
自己接受 TCP 连接(显式或替代 SSLServerSocket)
阅读 ClientHello 并解析您想要的片段,即 SNI 扩展
为
Socket
创建包装器记住这些数据,还有类似byte[]
的东西包含 ClientHello 和 whenread
被调用它首先返回已经读取的 ClientHello 然后从实际套接字读取,而write
其他操作照常进行创建服务器端
SSLSocket
“在”这个包装器套接字之上并像往常一样使用它当您想获取 SNI 时,例如在
X509KeyManager
中回调,而不是查看ExtendedSSLSession
来自[SSL]Socket
, 垂头丧气Socket
到您的包装器套接字并查看那里。 (您可以在socket instanceof MyWrapper
上设置此条件,这样当您进入 java8 时它会自行关闭。)
如果您使用 SSLEngine
接口(interface),您已经在管理连接和 I/O,所以您只需要执行 2、3A 和 5: 在将第一个输入 (ClientHello) 提供给 SSLEngine
之前解析它并在包装器中记住它,当你想查看它时使用包装器。
关于java - Java 7 中是否有等效的 getRequestedServerNames()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40771429/