如何从JavaScript中拒绝WebSocket打开握手读取状态代码?

时间:2014-02-13 18:31:08

标签: javascript websocket

我用JavaScript创建了一个WebSocket客户端

if ("WebSocket" in window) {            
    ws = new WebSocket(url);
    ws.binaryType = "arraybuffer";      
} else if ("MozWebSocket" in window) {  
    ws = new MozWebSocket(url);
    ws.binaryType = "arraybuffer";  
}

和WebSocket服务器应用程序。在某些情况下,我将服务器编程为拒绝连接请求并提供错误代码。

例如然后Firefox控制台显示一条消息

Firefox can't establish a connection to the server at ws://123.123.123.123:1234/.

并提供状态代码

HTTP/1.1 403 

这是我的WebSocket服务器发送的错误代码。

我的问题是:如何在我的JavaScript客户端中阅读此状态代码?

ws.onerror = function(e) {
    console.log(e);     
};   
ws.onclose = function(e) {
    console.log(e); 
};

都被调用,但没有一个Event对象包含此错误代码。

1 个答案:

答案 0 :(得分:8)

The spec forbids reading the HTTP status code (or anything like it) from the WebSocket object because otherwise the WebSocket object could be used to probe non-WebSocket endpoints, which would be a security issue:

User agents must not convey any failure information to scripts in a way that would allow a script to distinguish the following situations:

  • A server whose host name could not be resolved.
  • A server to which packets could not successfully be routed.
  • A server that refused the connection on the specified port.
  • A server that failed to correctly perform a TLS handshake (e.g., the server certificate can't be verified).
  • A server that did not complete the opening handshake (e.g. because it was not a WebSocket server).
  • A WebSocket server that sent a correct opening handshake, but that specified options that caused the client to drop the connection (e.g. the server specified a subprotocol that the client did not offer).
  • A WebSocket server that abruptly closed the connection after successfully completing the opening handshake.

https://www.w3.org/TR/websockets/#feedback-from-the-protocol


There is another way to do it though!

The WebSocket protocol allows for custom close codes:

4000-4999

Status codes in the range 4000-4999 are reserved for private use and thus can't be registered. Such codes can be used by prior agreements between WebSocket applications. The interpretation of these codes is undefined by this protocol.

https://tools.ietf.org/html/rfc6455#section-7.4.2

In your server-side logic, even when you ultimately want to reject the connection (like say the user is currently unauthenticated), do this instead:

  1. Accept the WebSocket connection
  2. Immediately close the connection with a custom close status

The client can now look at the CloseEvent.code to know why the connection was rejected.

You don't need to do this every time the server wants to reject a WebSocket connection. For example, I'd still reject the connection with a 4xx HTTP status if the request isn't a proper WebSocket request, or for security reasons (like if the anti-CSWSH Origin check fails). You only need to use the WebSocket close status for cases that you want the client-side logic to handle.