websocket通信之握手

1. 什么是握手

我们知道,所有的 tcp 请求都需要经历三次握手,如下图:

握手是websockets中的web,他是http到ws的桥梁 为什么是三次,如果是两次会怎么样呢,我们假象一下,

客户端:客户端请求连接

服务端:服务端回复客户端我已经准备好了

这时握手终止,服务端就会想,客户端内小子他有没有准备好啊,心好慌。。。

直到客户端回复,大哥我已经准备好了,来吧,开始干大事

2. 我们为什么握手


web现存的漏洞类,如果我们使用HTTP轮询存在于Web应用程序中使用http 如:

》以明文形式传输敏感数据(WS://而不是WSS://)
》用户输入验证问题
》身份验证/授权问题
》Origin Header验证/跨站请求伪造(CSRF)

感觉纯粹的ajax都不是很好解决,而在WebSocket握手期间可以对客户端进行身份验证的任何特定方式。WebSocket 
服务器可以使用通用HTTP服务器可用的任何客户端身份验证机制,例如cookie,HTTP身份验证或TLS 
身份验证

3. websocket握手 


Sec-WebSocket-Key头用于确保服务器不接受来自非 WebSocket客户端的连接

3.1 客户端握手请求 


标准的http版本必须是1.1或者更高,且请求方法必须为GET 示例:

GET /chat HTTP/1.1
Host: a.com:5000
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXdsZSBub25jZQ==
Sec-WebSocket-Version: 13

如果任何header未被识别或者传递了不正确的值,服务器应该发送 400 Bad Request 并立即关闭套接字。如果服务器不理解该版本的WebSockets 他应该发 Sec-WebSocket-Version回一个包含它理解的版本的头。

重点注意:客户端header中的 Sec-WebSocket-Key 是客户端连接服务端的唯一标志,每个发起的websocket都会带着这个唯一标志,没有的疑虑拒绝请求

【注意】
》所有的浏览器都会发送Origin 头 可以用此来进行安全检查,然后返回 403 fobidden
》可以根据requst-uri 在一台服务器上发布多个服务,/chat 可以聊天 /game 可以游戏
》常规的http状态码 只能在握手之前使用

3.2 服务端握手响应


当他接收到请求时,服务器应该发送一个非常奇怪(但仍是HTTP)的响应,就像下面这样(每个header
行后面必须加上\r\n 且在最后一个之后加一个额外的\r\n)

HTTP/1.1 101 Switching Protocols\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

现在我们说一下关键的客户端header中的 Sec-WebSocket-Key 和服务端响应header中的  Sec-WebSocket-Accept

服务器必须从客户端发送的 Sec-WebSocket-Key 派生出来得到 Sec-WebSocket-Accept

根据客户端生成的 Sec-WebSocket-Key 和 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" 连接到一起, 先使用 SHA-1 算法hash这个值 , 然后使用base64编码这个hash.如下:

$key = base64_encode(pack(
    'H*',
    sha1($matches[1] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')
));

一旦服务器发送了这些头文件,握手就完成了,我们就可以交换数据了,注意这里的 key 是固定的打包方式

【注意】
在发送回复握手之前,服务器可以发送其他头信息比如 Set-Cookie 或者使用其他状态码请求身份验证等

原文参考来自:https://tools.ietf.org/html/rfc6455#section-1.3  

猜你喜欢

转载自blog.csdn.net/wujiangwei567/article/details/81176141