websocket之四: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)必須遵守協議規范。但這不妨礙我們在協議切換完成后,進行鑒權授權:

鑒權

  1. 在連接建立時,檢查連接的HTTP請求頭信息(比如cookies中關於用戶的身份信息)
  2. 在每次接收到消息時,檢查連接是否已授權過,及授權是否過期
  3. 以上兩點,只要答案為否,則服務端主動關閉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 的哈希方法:

 

引用

    1. https://devcenter.heroku.com/articles/websocket-security
    2. https://tools.ietf.org/html/rfc6455
    3. https://zh.wikipedia.org/wiki/WebSocket

轉自:http://www.moye.me/2017/02/10/websocket-authentication-and-authorization/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM