WebSocket握手中Sec-WebSocket-Accept头部的值不正确。

5

我正在编写一个C++ WebSocket服务器,Chrome上的开发工具指出sec-websocket-accept头部值不正确。我已经测试了好几天,但看起来都没有问题。当客户端以readystate 3关闭而未调用WebSocket onopen时,虽然在Chrome开发工具中显示为101。

以下是我的密钥计算代码:

string magickey = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
string key = msgkey.append(magickey);

unsigned char* sha_str = SHA1(reinterpret_cast<const unsigned char*>(key.c_str()), key.length(), nullptr);
string acceptkey = base64_encode(reinterpret_cast<const unsigned char*>(sha_str), strlen((char*)sha_str));

string handshake_response = "HTTP/1.1 101 Switching Protocols\r\n";
handshake_response.append("Upgrade: websocket\r\n");
handshake_response.append("Connection: Upgrade\r\n");
handshake_response.append("Sec-WebSocket-Accept: "+acceptkey+"\r\n");
handshake_response.append("\r\n");  

Chrome响应

HTTP/1.1 101 Switching Protocols  
Upgrade: websocket  
Connection: Upgrade  
Sec-WebSocket-Accept: 5T5MvxP1iz40vLpi3kQs/ifDaCo=  

Chrome 请求

GET ws://localhost:4897/echo HTTP/1.1  
Host: localhost:4897  
Connection: Upgrade  
Pragma: no-cache  
Cache-Control: no-cache  
Upgrade: websocket  
Origin: http://localhost  
Sec-WebSocket-Version: 13  
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36  
Accept-Encoding: gzip, deflate, sdch  
Accept-Language: en-US,en;q=0.8  
Sec-WebSocket-Key: LKF8lHGznbKGIgO1UzAOhg==  
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits  

它说“在WebSocket握手期间发生错误:'Sec-WebSocket-Accept'头值不正确。”

Chrome还显示接收到一个额外的帧大小为79个字节,操作码为 -1。

非常感谢!


acceptkey 的值是多少? - Ilya
谢谢,我已经在问题中列出了关键值。 - xmxmxmx
你尝试过使用\n而不是\r\n吗?此外,从你的代码中,Chrome输出的行顺序似乎有所不同。 - Ilya
是的,\n 做完全相同的事情,我还编辑了 Chrome 输出,使其成为实际标头而不是解析过的。 - xmxmxmx
我正在使用Windows 8,因此/r/n应该是正确的。 - xmxmxmx
msgkey 的值是多少? - Ilya
1个回答

9

Chrome报告'Sec-WebSocket-Accept'不正确。我试图手动计算,我同意Chrome的说法。

我的测试:

  1. 连接 "LKF8lHGznbKGIgO1UzAOhg==" 和 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" => "LKF8lHGznbKGIgO1UzAOhg==258EAFA5-E914-47DA-95CA-C5AB0DC85B11",这是 key
  2. 计算SHA1 160位十六进制:bf15 14e3 7108 0ee4 7782 c709 a767 cc72 423d e5c4
  3. 根据您的日志,您的编码为base64:5T5MvxP1iz40vLpi3kQs/ifDaCo=
  4. 将其解码为十六进制:e53e 4cbf 13f5 8b3e 34bc ba62 de44 2cfe 27c3 682a

粗体值应该相等。如果我有任何错误,请随时纠正我。

可能出现的问题:

  • sha_str是否以null结尾?即strlen((char*)sha_str) == 20

  • signed/unsigned char混淆?


1
啊哈,我发现问题是原始密钥中有一个前导空格,所以SHA1是不正确的,正如你指出的那样,套接字已经打开,哇呼!非常感谢你。 - xmxmxmx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接