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

时间:2011-07-02 22:02:25

标签: java ssl

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

ServerSocket s = new ServerSocket(12345);

我想知道的是:有可能:

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

4 个答案:

答案 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)

根据您发布的内容,我认为这两项都没有。

  1. 如果ServerSocket上的监听器没有将请求解释为HTTP,那么就没有任何魔力可以实现这一点。
  2. 如果ServerSocket上的监听者没有解密加密的请求,那么就没有任何魔力可以实现这一点。
  3. 您是否编写了在ServerSocket上收听的代码?如果是,您可以通过查看您的代码来回答您自己的问题。

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