是否可以将普通套接字更改为SSLSocket?
有一个普通的套接字服务器侦听端口12345
;
ServerSocket s = new ServerSocket(12345);
我想知道的是:有可能:
- 如果客户端发送
http
请求,服务器直接处理请求, - 如果客户端发送
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接口,而不是尝试自动内容嗅探。
根据你发布的内容,我认为两者都不是。
- 如果
ServerSocket
上的监听器没有将请求解释为HTTP,那么就没有任何魔法可以实现。 - 如果
ServerSocket
上的监听器没有解密加密的请求,那么就没有任何魔法可以实现。
你是否编写了在ServerSocket
上监听的代码? 如果是,您可以通过查看您的代码来回答您自己的问题。
有人写了正在侦听ServerSocket
的代码吗? 如果是,你将不得不问他们。 您是否提供了有关预期协议的任何信息?