netty4 websocket 响应返回401,浏览器没有任何反应?

我在使用netty开发websocket服务器,浏览器使用var socket = new WebSocket("ws://127.0.0.1:18080/ws?token=xxxx");连接时服务器将验证token,如果不通过则返回401并关闭socket。
服务器响应代码:

    private void httpResponse401(ChannelHandlerContext ctx, FullHttpRequest request){
        FullHttpResponse response = new DefaultFullHttpResponse(request.protocolVersion(), HttpResponseStatus.UNAUTHORIZED);
        response.headers().set(HttpHeaderNames.CONTENT_LENGTH, 0);
        ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
        ReferenceCountUtil.release(request);
    }

目前情况是socket虽然关闭,但浏览器好像没有收到401的响应。我需要在浏览器种能知道连接关闭是因为401还是其他什么情况。
image.png
image.png

阅读 554
avatarAI BotBETA

问题中的关键在于 WebSocket 连接与 HTTP 连接之间的差异。当你使用 WebSocket API (new WebSocket(...)) 连接到服务器时,你实际上正在建立一个持久的双向连接,不同于传统的 HTTP 连接。这意味着 WebSocket 连接并不遵循标准的 HTTP 响应代码(如 401)。

WebSocket 连接一旦建立,服务器不能通过发送 HTTP 响应代码来关闭连接。因此,在你的代码中,尽管你发送了一个 401 响应并关闭了连接,浏览器可能并没有正确地识别这个响应,因为它不符合 WebSocket 的协议。

如果你想在 WebSocket 连接中处理身份验证,你应该在你的应用程序协议中定义一种方式来传达身份验证失败。这通常意味着在 WebSocket 连接建立后,你需要定义一种消息格式,让服务器能够发送一个特殊的消息,告知客户端身份验证失败,然后客户端可以据此关闭连接。

例如,你可以在 WebSocket 握手成功后,发送一个包含身份验证信息的消息给服务器。如果服务器验证失败,它可以发送一个特定的消息(如一个包含错误码的消息)给客户端,然后客户端可以根据这个消息来关闭 WebSocket 连接。

以下是一个简单的例子:

服务器端

// 假设你有一个处理 WebSocket 消息的方法
public void handleWebSocketMessage(ChannelHandlerContext ctx, TextWebSocketFrame frame) {
    String message = frame.text();
    // 解析消息并验证 token
    if (!validateToken(message)) {
        // 发送一个表示身份验证失败的消息
        ctx.writeAndFlush(new TextWebSocketFrame("ERROR: 401 Unauthorized"));
        ctx.close();
    } else {
        // 处理正常消息
    }
}

客户端

var socket = new WebSocket("ws://127.0.0.1:18080/ws?token=xxxx");

socket.onmessage = function(event) {
    var message = event.data;
    if (message.startsWith("ERROR:")) {
        // 解析错误消息并处理
        var errorCode = message.split(":")[1];
        if (errorCode === "401") {
            console.log("WebSocket connection closed due to unauthorized access.");
            socket.close();
        }
    } else {
        // 处理正常消息
    }
};

这样,当服务器发送一个表示身份验证失败的消息时,客户端就可以捕获到这个消息,并据此关闭 WebSocket 连接。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏