有一个普通的套接字服务器侦听端口12345
;
ServerSocket s = new ServerSocket(12345);
我想知道的是:有可能:
http
请求,则服务器直接处理请求https
请求,服务器将客户端套接字更改为SSLSocket? 由于
答案 0 :(得分:20)
是否可以更改普通插槽 到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请求,则服务器更改客户端 socket到SSLSocket?
再次,是的,这是可能的。它有时被称为“端口统一”,它是implemented in Grizzly,因而是Glassfish。
它的工作原理是因为HTTP和TLS(HTTPS工作)都是预期客户端首先进行通信的协议。因此,服务器可以检测客户端最初发送的是TLS ClientHello
消息(在这种情况下应该尝试继续进行TLS握手)还是普通HTTP请求(例如GET / HTTP/1.1
... )。
我怀疑端口统一使用SSLEngine
“更容易”,否则,在普通套接字上实现预读可能很困难,您仍然可以通过{{1}进行转换}。
请注意,这仍然很不寻常。
答案 1 :(得分:3)
无法在同一端口上同时提供http和https。但是,如果客户端和服务器都支持TLS,理论上可以升级现有的http连接以使用TLS ,见RFC 2817。 SSLSocketFactory类有一个createSocket()函数,可用于将现有套接字升级到SSL / TLS。
免责声明:我没有尝试过这样做,实施RFC 2817可能并非易事。
编辑:显然我错了,就像Bruno写的那样可以使用称为端口统一的技术在同一端口上提供http和https,该技术使用收到的前几个字节来检测协议。 Netty(JBoss)框架中包含example个。{/ p>
答案 2 :(得分:1)
Socket / SSLSocket接口在这里不允许方便的内容识别 - 当你从套接字开始读取并看到它只是垃圾(不是普通的HTTP)时,你无法将这些数据提供给一个新的SSLSocket包裹正常的。
您可以使用Socket(或SocketChannel)查看数据,然后(如果它不是普通HTTP请求的开头)将相同的数据传递给SSLEngine对象进行解密/加密。这意味着你必须自己处理所有的加密/解密调用,这不是完全无关紧要的(至少,它比使用SSLSocket的两个流更复杂 - 我曾经做过一次)。
当然,如果你这样做,你可能会更好地实现RFC 2817界面,而不是尝试自动内容嗅探。
答案 3 :(得分:0)
根据您发布的内容,我认为这两项都没有。
ServerSocket
上的监听器没有将请求解释为HTTP,那么就没有任何魔力可以实现这一点。ServerSocket
上的监听者没有解密加密的请求,那么就没有任何魔力可以实现这一点。您是否编写了在ServerSocket
上收听的代码?如果是,您可以通过查看您的代码来回答您自己的问题。
是否其他人编写了正在ServerSocket
上收听的代码?如果是,你将不得不问他们。您是否提供了有关预期协议的任何信息?