WebSocket 作為實時通信的利器,越來越受到開發者的青睞。然而,為了確保通信的安全性和合法性,鑒權成為不可或缺的一環。本文將深入探討 WebSocket 的鑒權機制,為你呈現一攬子的解決方案,確保你的 WebSocket 通信得心應手。

使用場景
WebSocket 鑒權在許多場景中都顯得尤為重要。例如,實時聊天應用、在線協作工具、實時數據更新等情境都需要對 WebSocket 進行鑒權,以確保只有合法的用戶或服務可以進行通信。通過本文的指導,你將更好地了解在何種場景下使用 WebSocket 鑒權是有意義的。
WebSocket 調試工具
要調試 WebSocket,那就需要一個好的調試工具,這里我比較推薦 Apifox。它支持調試 http(s)、WebSocket、Socket、gRPC、Dubbo 等多種協議的接口,這使得它成為了一個非常全面的接口測試工具!

常見方法
方法 1:基于 Token 的鑒權
WebSocket 鑒權中,基于 Token 的方式是最為常見和靈活的一種。通過在連接時攜帶 Token,服務器可以驗證用戶的身份。以下是一個簡單的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | const WebSocket = require( 'ws' ); const server = new WebSocket.Server({ port: 3000 }); server.on( 'connection' , (socket, req) => { ???? const token = req.headers[ 'sec-websocket-protocol' ]; ???? ? ???? // 驗證token的合法性 ???? if (isValidToken(token)) { ???????? // 鑒權通過,進行后續操作 ???????? socket.send( '鑒權通過,歡迎連接!' ); ???? } else { ???????? // 鑒權失敗,關閉連接 ???????? socket.close(); ???? } }); |
方法 2:基于簽名的鑒權
另一種常見的鑒權方式是基于簽名的方法。通過在連接時發送帶有簽名的信息,服務器驗證簽名的合法性。以下是一個簡單的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | const WebSocket = require( 'ws' ); const crypto = require( 'crypto' ); const server = new WebSocket.Server({ port: 3000 }); server.on( 'connection' , (socket, req) => { ???? const signature = req.headers[ 'x-signature' ]; ???? const data = req.url + req.headers[ 'sec-websocket-key' ]; ???? ? ???? // 驗證簽名的合法性 ???? if (isValidSignature(signature, data)) { ???????? // 鑒權通過,進行后續操作 ???????? socket.send( '鑒權通過,歡迎連接!' ); ???? } else { ???????? // 鑒權失敗,關閉連接 ???????? socket.close(); ???? } }); |
方法 3:基于 IP 白名單的鑒權
在某些情況下,你可能希望限制 WebSocket 連接只能來自特定 IP 地址范圍。這時可以使用基于 IP 白名單的鑒權方式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | const WebSocket = require( 'ws' ); const allowedIPs = [ '192.168.0.1' , '10.0.0.2' ]; const server = new WebSocket.Server({ port: 3000 }); server.on( 'connection' , (socket, req) => { ???? const clientIP = req.connection.remoteAddress; ???? ? ???? // 驗證連接是否在白名單中 ???? if (allowedIPs.includes(clientIP)) { ???????? // 鑒權通過,進行后續操作 ???????? socket.send( '鑒權通過,歡迎連接!' ); ???? } else { ???????? // 鑒權失敗,關閉連接 ???????? socket.close(); ???? } }); |
方法 4:基于 OAuth 認證的鑒權
在需要與現有身份驗證系統集成時,OAuth 認證是一種常見的選擇。通過在連接時使用 OAuth 令牌,服務器可以驗證用戶的身份。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | const WebSocket = require( 'ws' ); const axios = require( 'axios' ); const server = new WebSocket.Server({ port: 3000 }); server.on( 'connection' , async (socket, req) => { ???? const accessToken = req.headers[ 'authorization' ]; ???? ? ???? // 驗證OAuth令牌的合法性 ???? try { ???????? const response = await axios.get( 'https://oauth-provider.com/verify' , { ???????????? headers: { Authorization: `Bearer ${accessToken}` } ???????? }); ???????? if (response.data.valid) { ???????????? // 鑒權通過,進行后續操作 ???????????? socket.send( '鑒權通過,歡迎連接!' ); ???????? } else { ???????????? // 鑒權失敗,關閉連接 ???????????? socket.close(); ???????? } ???? } catch (error) { ???????? // 驗證失敗,關閉連接 ???????? socket.close(); ???? } }); |
其他常見方法...
除了以上介紹的方式,還有一些其他的鑒權方法,如基于 API 密鑰、HTTP 基本認證等。根據具體需求,選擇最適合項目的方式。
實踐案例
基于 Token 的鑒權實踐
- 在 WebSocket 連接時,客戶端攜帶 Token 信息。
- 服務器接收 Token 信息并驗證其合法性。
- 根據驗證結果,允許或拒絕連接。
1 2 | // 客戶端代碼 const socket = new WebSocket( 'ws://localhost:3000' , [ 'Bearer YOUR_TOKEN' ]); |
1 2 3 4 5 6 7 8 9 10 | // 服務器端代碼 server.on( 'connection' , (socket, req) => { ???? const token = req.headers[ 'sec-websocket-protocol' ]; ???? ? ???? if (isValidToken(token)) { ???????? socket.send( '鑒權通過,歡迎連接!' ); ???? } else { ???????? socket.close(); ???? } }); |
基于簽名的鑒權實踐
- 在 WebSocket 連接時,客戶端計算簽名并攜帶至服務器。
- 服務器接收簽名信息,驗證其合法性。
- 根據驗證結果,允許或拒絕連接。
1 2 | // 客戶端代碼 const socket = new WebSocket( 'ws://localhost:3000' , { headers: { 'X-Signature' : calculateSignature() } }); |
1 2 3 4 5 6 7 8 9 10 11 | // 服務器端代碼 server.on( 'connection' , (socket, req) => { ???? const signature = req.headers[ 'x-signature' ]; ???? const data = req.url + req.headers[ 'sec-websocket-key' ]; ???? ? ???? if (isValidSignature(signature, data)) { ???????? socket.send( '鑒權通過,歡迎連接!' ); ???? } else { ???????? socket.close(); ???? } }); |
基于 IP 白名單的鑒權實踐
- 在 WebSocket 連接時,服務器獲取客戶端 IP 地址。
- 驗證 IP 地址是否在白名單中。
- 根據驗證結果,允許或拒絕連接。
1 2 3 4 5 6 7 8 9 10 | // 服務器端代碼 server.on( 'connection' , (socket, req) => { ???? const clientIP = req.connection.remoteAddress; ???? ? ???? if (allowedIPs.includes(clientIP)) { ???????? socket.send( '鑒權通過,歡迎連接!' ); ???? } else { ???????? socket.close(); ???? } }); |
基于 OAuth 認證的鑒權實踐
- 在 WebSocket 連接時,客戶端攜帶 OAuth 令牌。
- 服務器調用 OAuth 服務驗證令牌的合法性。
- 根據驗證結果,允許或拒絕連接。
1 2 | // 客戶端代碼 const socket = new WebSocket( 'ws://localhost:3000' , { headers: { 'Authorization' : 'Bearer YOUR_ACCESS_TOKEN' } }); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // 服務器端代碼 server.on( 'connection' , async (socket, req) => { ???? const accessToken = req.headers[ 'authorization' ]; ???? ? ???? try { ???????? const response = await axios.get( 'https://oauth-provider.com/verify' , { ???????????? headers: { Authorization: `Bearer ${accessToken}` } ???????? }); ???????? if (response.data.valid) { ???????????? socket.send( '鑒權通過,歡迎連接!' ); ???????? } else { ???????????? socket.close(); ???????? } ???? } catch (error) { ???????? socket.close(); ???? } }); |
提示、技巧和注意事項
- 在選擇鑒權方式時,要根據項目的實際需求和安全性要求進行合理選擇。
- 對于基于 Token 的鑒權,建議使用 JWT(JSON Web Token)來提高安全性。
- 在驗證失敗時,及時關閉連接,以防止未授權的訪問。
在 Apifox 中調試 WebSocket
如果你要調試 WebSocket 接口,并確保你的應用程序能夠正常工作。這時,一個強大的接口測試工具就會派上用場。
Apifox 是一個比 Postman 更強大的接口測試工具,Apifox = Postman + Swagger + Mock + JMeter。它支持調試 http(s)、WebSocket、Socket、gRPC、Dubbo 等多種協議的接口,這使得它成為了一個非常全面的接口測試工具,所以強烈推薦去下載體驗!
首先在 Apifox 中新建一個 HTTP 項目,然后在項目中添加 WebSocket 接口。


接著輸入 WebSocket 的服務端 URL,例如:ws://localhost:3000
,然后保存并填寫接口名稱,然后確定即可。


點擊“Message 選項”然后寫入“你好啊,我是 Apifox”,然后點擊發送,你會看到服務端和其它客戶端都接收到了信息,非常方便,快去試試吧!

以下用 Node.js 寫的 WebSocket 服務端和客戶端均收到了消息。

總結
通過本文的介紹,你應該對 WebSocket 鑒權有了更清晰的認識。不同的鑒權方式各有優劣,你可以根據具體情況選擇最適合自己項目的方式。在保障通信安全的同時,也能提供更好的用戶體驗。
參考鏈接
- MDN Web Docs - WebSocket
- JSON Web Tokens
- OAuth 2.0
學習更多: