【问题标题】:Websocket 'Sec-WebSocket-Accept' header mismatch between ReactJS client and Node.js serverReactJS 客户端和 Node.js 服务器之间的 Websocket 'Sec-WebSocket-Accept' 标头不匹配
【发布时间】:2019-08-07 02:55:15
【问题描述】:

我正在使用 WebSockets 和端口 8080 上的 React 客户端(使用 Webpack devServer 运行)和端口 5000 上的节点服务器和套接字编写应用程序。但是,初始握手总是失败并出现错误:WebSocket connection to 'ws://localhost:5000/' failed: Error during WebSocket handshake: Incorrect 'Sec-WebSocket-Accept' header value

为确保,我使用 Chrome 开发工具检查了 React 应用程序的请求和响应,并查看以下内容:

在我的节点服务器上,我记录了 sec-websocket-accept 标头接受键,以及我的响应标头,并得到以下信息:

看起来确实如此,键不匹配。事实上,它们似乎根本不是相同的键。 React 客户端和 Node 服务器(例如我用于 React 的 Webpack 开发服务器)之间是否有什么东西正在改变它们?

我的反应代码:

    componentDidMount(){
        this.socket = new WebSocket('ws://localhost:5000', ['json']);
        this.socket.onerror = err => {
            console.log(err)
        }
        this.socket.onmessage = e => {
            let res = JSON.parse(e.data);
            console.log(e, res);
            let copyArr = [...this.state.message]
            copyArr.push(res);

            this.setState({
                message: copyArr
            });
        }
    }

我的 Node.js 代码:

const server = http.createServer();

server.on('upgrade', (req, socket) => {

    if(req.headers['upgrade'] !== "websocket"){
        socket.end('HTTP/1.1 400 Bad Request');
        return;
    }

    const acceptKey = req.headers['sec-websocket-key'];
    const acceptHash = generateValue(acceptKey);

    console.log('accepkey', acceptKey, 'hash', acceptHash);

    const resHeaders = [ 'HTTP/1.1 101 Web Socket Protocol Handshake', 'Upgrade: WebSocket', 'Connection: Upgrade', `Sec-WebSocket-Accept: ${acceptHash}` ];

    console.log(resHeaders);

    let protocols = req.headers['sec-websocket-protocol'];
    protocols = !protocols ? [] : protocols.split(',').map(name => name.trim());

    if(protocols.includes('json')){
        console.log('json here');
        resHeaders.push(`Sec-WebSocket-Protocol: json`);
    }

    socket.write(resHeaders.join('\r\n') + '\r\n\r\n');
})

function generateValue(key){
    return crypto
      .createHash('sha1')
      .update(key + '258EAFA5-E914–47DA-95CA-C5AB0DC85B11', 'binary')
      .digest('base64');
}

【问题讨论】:

    标签: node.js reactjs sockets websocket


    【解决方案1】:

    'S1cb73xifMvqiIpMjvBabg==' 键的正确接受哈希是 'R35dUOuC/ldiVp1ZTchRsiHUnvo='。

    您的 generateValue() 函数计算的哈希值不正确,因为它在 GUID 字符串“258EAFA5-E914–47DA-95CA-C5AB0DC85B11”中的字符不正确。如果您仔细观察,您会发现第二个破折号在“...14–47...”中与其他破折号不同。它应该是带有字符代码 45 的普通 ASCII 破折号或连字符,但实际上它是带有字符代码 8211 的 Unicode 破折号。不同的字符代码会导致计算失败。

    修复该字符将使您的 WebSocket 客户端更快乐。

    【讨论】:

      【解决方案2】:

      对于任何想知道的人来说,就我而言,导致问题的罪魁祸首是我在 Node.js 服务器中编写标头后添加的额外的新行和返回。把它们拿出来做:

      socket.write(resHeaders.join('\r\n'));
      

      代替:

      socket.write(resHeaders.join('\r\n') + '\r\n\r\n');
      

      为我解决了握手不匹配问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-04
        • 2016-04-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多