You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot WebSocket拦截器校验失败时前端无法获取提示信息问题

WebSocket握手Token校验失败后前端无法获取提示的解决方案

问题原因

当前代码直接写入ServerHttpResponse输出流,但未正确设置响应头、未确保流完成刷新关闭,再加上WebSocket API的浏览器安全限制,导致前端无法正常获取响应提示内容。

后端代码修正

修改beforeHandshake方法中的失败处理逻辑,改用原生HttpServletResponse构建响应,确保内容能正确发送:

@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
    String token = extractToken((ServletServerHttpRequest) request);
    if (!validateToken(token)) {
        // 转换为原生HttpServletResponse处理
        ServletServerHttpResponse servletResponse = (ServletServerHttpResponse) response;
        HttpServletResponse httpResponse = servletResponse.getServletResponse();
        
        // 设置状态码和响应头
        httpResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
        httpResponse.setContentType("text/plain;charset=UTF-8");
        
        // 写入提示信息并确保输出完成
        PrintWriter writer = httpResponse.getWriter();
        writer.write("Token校验失败,请检查Token是否有效");
        writer.flush();
        writer.close();
        
        return false;
    }
    return true;
}

前端处理方案

由于浏览器WebSocket API的安全限制,onerror事件无法直接获取HTTP响应体,可通过以下两种方式处理:

方式1:先通过HTTP请求预校验Token

在建立WebSocket连接前,先发送GET请求到握手地址校验Token,通过后再创建WebSocket连接:

async function connectWebSocket(token) {
    try {
        // 预校验Token
        const checkResponse = await fetch(`/ws?token=${token}`, { method: 'GET' });
        if (!checkResponse.ok) {
            const errorMsg = await checkResponse.text();
            alert(errorMsg);
            return;
        }
        // 校验通过,建立WebSocket连接
        const ws = new WebSocket(`ws://localhost:8080/ws?token=${token}`);
        // 后续WebSocket事件处理
        ws.onopen = () => console.log('连接成功');
        ws.onclose = (event) => console.log('连接关闭', event);
        ws.onerror = (error) => console.error('连接错误', error);
    } catch (err) {
        alert('连接失败:' + err.message);
    }
}

方式2:根据WebSocket关闭事件状态码判断

后端返回401状态码后,前端在onclose事件中通过event.code推断错误类型(WebSocket关闭码1006/1008通常对应握手失败场景):

const ws = new WebSocket(`ws://localhost:8080/ws?token=${invalidToken}`);
ws.onclose = (event) => {
    if (event.code === 1006 || event.code === 1008) {
        alert('Token校验失败,请检查Token是否有效');
    } else {
        alert('连接关闭:' + event.reason);
    }
};
ws.onerror = (error) => {
    console.error('连接错误', error);
};

内容的提问来源于stack exchange,提问作者chenxin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 01:57:36