是否可以将普通套接字更改为SSLSocket?

有一个普通的套接字服务器侦听端口12345 ;

 ServerSocket s = new ServerSocket(12345); 

我想知道的是:有可能:

  1. 如果客户端发送http请求,服务器直接处理请求,
  2. 如果客户端发送https请求,服务器将客户端套接字更改为SSLSocket?

谢谢

是否可以将普通套接字更改为SSLSocket?

是的。 在服务器端,以下工作:

 ServerSocketFactory ssf = ServerSocketFactory.getDefault(); ServerSocket serverSocket = ssf.createServerSocket(12345); // I've initialised an sslContext with a keystore, as you normally would. Socket socket = serverSocket.accept(); SSLSocketFactory sslSf = sslContext.getSocketFactory(); // The host name doesn't really matter, since we're turning it into a server socket // (No need to match the host name to the certificate on this side). SSLSocket sslSocket = (SSLSocket) sslSf.createSocket(socket, null, socket.getPort(), false); sslSocket.setUseClientMode(false); // Use the sslSocket InputStream/OutputStream as usual. 

SSLSocketFactory.createSocket(Socket, ...)默认情况下会将现有Socket转换为客户端模式SSLSocket 。 由于握手仅在您开始使用I / O流进行读/写时开始,因此仍然需要使用setUseClientMode(false)更改模式。

关于其余问题:

我想知道的是:有可能:

  • 如果客户端发送http请求,服务器直接处理请求,
  • 如果客户端发送https请求,服务器将客户端套接字更改为SSLSocket?

再次,是的,这是可能的。 它有时被称为“ 港口统一 ”,它在Grizzly和Glassfish中实施 。

它的工作原理是因为HTTP和TLS(HTTPS工作)都是预期客户端首先进行通信的协议。 因此,服务器可以检测客户端最初发送的是TLS ClientHello消息(在这种情况下应该尝试继续进行TLS握手)还是普通HTTP请求(例如GET / HTTP/1.1 …)。

我怀疑端口统一使用SSLEngine “更容易”,否则,在普通套接字上实现预读很难,你仍然可以通过SSLSocketFactory.createSocket(Socket, ...)进行转换。

但请注意,这仍然很不寻常。

无法在同一端口上同时提供http和https。 但是,如果客户端和服务器都支持TLS,理论上应该可以升级现有的http连接以使用TLS,请参阅RFC 2817 。 SSLSocketFactory类有一个createSocket()函数,可用于将现有套接字升级到SSL / TLS。

免责声明:我没有尝试过这样做,实施RFC 2817可能并非易事。

编辑:显然我错了,就像Bruno写的那样可以使用称为端口统一的技术在同一端口上提供http和https,它使用收到的前几个字节来检测协议。 Netty(JBoss)框架中包含了一个这样的例子 。

Socket / SSLSocket接口在这里不允许方便的内容识别 – 当你从套接字开始读取并看到它只是垃圾(不是普通的HTTP)时,你不能将这些数据提供给一个正常的新SSLSocket。 。

您可以使用Socket(或SocketChannel)查看数据,然后(如果它不是普通HTTP请求的开头)将相同的数据传递给SSLEngine对象进行解密/加密。 这意味着你必须自己处理所有的加密/解密调用,这不是完全无关紧要的(至少,它比简单地使用带有两个流的SSLSocket复杂得多 – 我做过一次)。

当然,如果你这样做,你可能更好地实现RFC 2817接口,而不是尝试自动内容嗅探。

根据你发布的内容,我认为两者都不是。

  1. 如果ServerSocket上的监听器没有将请求解释为HTTP,那么就没有任何魔法可以实现。
  2. 如果ServerSocket上的监听器没有解密加密的请求,那么就没有任何魔法可以实现。

你是否编写了在ServerSocket上监听的代码? 如果是,您可以通过查看您的代码来回答您自己的问题。

有人写了正在侦听ServerSocket的代码吗? 如果是,你将不得不问他们。 您是否提供了有关预期协议的任何信息?