Websocket握手:“ Sec-WebSocket-Accept”标头值不正确

时间:2019-02-22 16:35:54

标签: websocket

我正在用C ++编写Websocket服务器,但无法正常工作。 Chrome报告该错误是由于接受标头错误,但我认为该值是正确的。

作为一个示例交换,客户端发送以下密钥:

Sec-WebSocket-Key: ypX0m2zum/pt80mxlVo8PA==

我的服务器发回邮件:

Sec-WebSocket-Accept: Kl4mnqm5QA6bBmGf3EAN0nyGXws=

我已经针对RFC中的示例测试了服务器,并且将其签出。我不知道为什么它不被接受。我的理论是,我必须做其他事情,产生与错误的接受值相同的错误。

以下是Wireshark捕获的不同请求:

Hypertext Transfer Protocol
    GET /websocket HTTP/1.1\r\n
    Host: 127.0.0.1:8443\r\n
    Connection: Upgrade\r\n
    Pragma: no-cache\r\n
    Cache-Control: no-cache\r\n
    User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36\r\n
    Upgrade: websocket\r\n
    Origin: chrome-extension://eajaahbjpnhghjcdaclbkeamlkepinbl\r\n
    Sec-WebSocket-Version: 13\r\n
    Accept-Encoding: gzip, deflate, br\r\n
    Accept-Language: en-US,en;q=0.9\r\n
    Sec-WebSocket-Key: +zJ3/KI/Zrumgh+AjxopRQ==\r\n
    Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n
    \r\n
    [Full request URI: http://127.0.0.1:8443/websocket]
    [HTTP request 1/1]
    [Response in frame: 6]

这是响应:

Hypertext Transfer Protocol
    HTTP/1.1 101 Switching Protocols\r\n
    Upgrade: websocket\r\n
    Connection: Upgrade\r\n
    Sec-WebSocket-Accept: anTEIFyI/gTepr8Q3okBj81M2/4=\r\n
    \r\n
    [HTTP response 1/1]
    [Time since request: 0.000245010 seconds]
    [Request in frame: 4]

有人可以告诉我回答有什​​么问题吗?我的接受值不正确吗?

编辑1:

我用来创建响应值的代码。在此之前,从请求中获取了websocket_key。

    const char *magic_string = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

    int pre_hash_size = 36 + websocket_key.size();
    char pre_hash[pre_hash_size];

    memcpy(pre_hash, websocket_key.c_str(), websocket_key.size());
    memcpy(pre_hash + websocket_key.size(), magic_string, 36);

    unique_ptr<Botan::HashFunction> hash1(Botan::HashFunction::create("SHA-1"));
    Botan::secure_vector<uint8_t> post_hash = hash1->process(reinterpret_cast<const uint8_t *>(pre_hash), pre_hash_size);

    string accept_response = base64_encode(post_hash.data(), post_hash.size());

这是基数为64的函数:

/* 
   base64.cpp and base64.h
   base64 encoding and decoding with C++.
   Version: 1.01.00
   Copyright (C) 2004-2017 René Nyffenegger
   This source code is provided 'as-is', without any express or implied
   warranty. In no event will the author be held liable for any damages
   arising from the use of this software.
   Permission is granted to anyone to use this software for any purpose,
   including commercial applications, and to alter it and redistribute it
   freely, subject to the following restrictions:
   1. The origin of this source code must not be misrepresented; you must not
      claim that you wrote the original source code. If you use this source code
      in a product, an acknowledgment in the product documentation would be
      appreciated but is not required.
   2. Altered source versions must be plainly marked as such, and must not be
      misrepresented as being the original source code.
   3. This notice may not be removed or altered from any source distribution.
   René Nyffenegger rene.nyffenegger@adp-gmbh.ch
*/

static const std::string base64_chars =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789+/";

std::string base64_encode(unsigned char const *bytes_to_encode, unsigned int in_len)
{
  std::string ret;
  int i = 0;
  int j = 0;
  unsigned char char_array_3[3];
  unsigned char char_array_4[4];

  while (in_len--)
  {
    char_array_3[i++] = *(bytes_to_encode++);
    if (i == 3)
    {
      char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
      char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
      char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
      char_array_4[3] = char_array_3[2] & 0x3f;

      for (i = 0; (i < 4); i++)
        ret += base64_chars[char_array_4[i]];
      i = 0;
    }
  }

  if (i)
  {
    for (j = i; j < 3; j++)
      char_array_3[j] = '\0';

    char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
    char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
    char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);

    for (j = 0; (j < i + 1); j++)
      ret += base64_chars[char_array_4[j]];

    while ((i++ < 3))
      ret += '=';
  }

  return ret;
}

1 个答案:

答案 0 :(得分:1)

问题是,当我将websocket密钥(由客户端发送)中的pre_hash字符串和魔术字符串(常量)连接在一起时,我没有考虑 size()函数所包含的空终止符这是计数。 我在解析请求标头时无意中添加了额外的空间。

记住小子,C ++字符串以null结尾,并且size()反映了这一点。

相关问题