WebSocket 的鑒權授權方案
引子
WebSocket 是個好東西,為我們提供了便捷且實時的通訊能力。然而,對于 WebSocket 客戶端的鑒權,協議的 RFC 是這么說的:
This protocol doesn’t prescribe any particular way that servers can
authenticate clients during the WebSocket handshake. The WebSocket
server can use any client authentication mechanism available to a
generic HTTP server, such as cookies, HTTP authentication, or TLS
authentication.
也就是說,鑒權這個事,得自己動手
協議原理
WebSocket 是獨立的、創建在 TCP 上的協議。
為了創建Websocket連接,需要通過瀏覽器發出請求,之后服務器進行回應,這個過程通常稱為“握手”。
實現步驟:
1. 發起請求的瀏覽器端,發出協商報文:
2. 服務器端響應101狀態碼(即切換到socket通訊方式),其報文:
3. 協議切換完成,雙方使用Socket通訊
直觀的協商及通訊過程:
方案
通過對協議實現的解讀可知:在 HTTP 切換到 Socket 之前,沒有什么好的機會進行鑒權,因為在這個時間節點,報文(或者說請求的Headers)必須遵守協議規范。但這不妨礙我們在協議切換完成后,進行鑒權授權:
鑒權
在連接建立時,檢查連接的HTTP請求頭信息(比如cookies中關于用戶的身份信息)
在每次接收到消息時,檢查連接是否已授權過,及授權是否過期
以上兩點,只要答案為否,則服務端主動關閉socket連接
授權
服務端在連接建立時,頒發一個ticket給peer端,這個ticket可以包含但不限于:
peer端的uniqueId(可以是ip,userid,deviceid…任一種具備唯一性的鍵)
過期時間的timestamp
token:由以上信息生成的哈希值,最好能加鹽
安全性的補充說明
有朋友問:這一套機制如何防范重放攻擊,私以為可以從以下幾點出發:
可以用這里提到的expires,保證過期,如果你愿意,甚至可以每次下發消息時都發送一個新的Ticket,只要上傳消息對不上這個Ticket,就斷開,這樣非Original Peer是沒法重放的
可以結合redis,實現 ratelimit,防止高頻刷接口,這個可以參考 express-rate-limit,原理很簡單,不展開
為防止中間人,最好使用wss(TLS)
代碼實現
WebSocket連接處理,基于 node.js 的 ws 實現:
授權用到的 Ticket(這里存儲用到的是knex + postgreSQL):
utils 的哈希方法:
掃描二維碼推送至手機訪問。
版權聲明:本文由短鏈接發布,如需轉載請注明出處。
本文鏈接:http://www.virginiabusinesslawupdate.com/article_382.html