【发布时间】:2011-07-02 22:02:24
【问题描述】:
有一个普通的套接字服务器在端口12345上监听;
ServerSocket s = new ServerSocket(12345);
我想知道的是有可能:
- 如果客户端发送
http请求,服务器直接处理请求, - 如果客户端发送
https请求,服务器将客户端套接字更改为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?
再次,是的,这是可能的。它有时被称为“端口统一”,它是implemented in Grizzly,因此是Glassfish。
它之所以有效,是因为 HTTP 和 TLS(HTTPS 在其上工作)都是期望客户端首先对话的协议。因此,服务器可以检测客户端最初发送的是 TLS ClientHello 消息(在这种情况下它应该尝试进行 TLS 握手)还是普通的 HTTP 请求(例如 GET / HTTP/1.1...)。
我怀疑使用SSLEngine 进行端口统一“更容易”,否则,可能很难在普通套接字上实现预读,您仍然可以通过SSLSocketFactory.createSocket(Socket, ...) 进行转换。
请注意,这仍然是相当不寻常的。
【讨论】:
【讨论】:
这里的 Socket/SSLSocket 接口不允许方便的内容识别 - 当您开始从套接字读取并看到它只是垃圾(不是纯 HTTP)时,您无法将此数据提供给包裹的新 SSLSocket一个普通的。
您可以使用 Socket(或 SocketChannel)并查看数据,然后(如果它不是普通 HTTP 请求的开始)将相同的数据传递给 SSLEngine 对象以进行解密/加密。这意味着您必须自己处理所有加密/解密调用,这并非完全无关紧要(至少,它比简单地使用带有两个流的 SSLSocket 复杂得多——我做过一次)。
当然,如果您这样做,您可能会更好地实现 RFC 2817 接口,而不是尝试自动内容嗅探。
【讨论】:
SSLEngine 之外的其他解决方案(主要是因为它很难使用),但您是否暗示您仍在使用 Java5 之前的 JDK? @Paŭlo Ebermann,实现 RFC 2817 的问题在于,据我所知,几乎没有客户端支持它,而查看数据原则上适用于任何 HTTP/HTTPS 客户端(尽管至少一个 URL 必须指定端口明确)。
根据您发布的内容,我认为这两个方面都不是。
ServerSocket 上的侦听器没有将请求解释为 HTTP,那么没有什么魔法可以做到这一点。ServerSocket 上的侦听器没有解密加密的请求,那么没有什么魔法可以做到这一点。您是否编写了监听ServerSocket 的代码?如果是,您可以通过查看您的代码来回答您自己的问题。
是否有人编写了正在监听ServerSocket 的代码?如果是,您将不得不问他们。您是否提供了有关预期协议的任何信息?
【讨论】:
ClientHello还是一个有效的普通HTTP请求。