在现代Web应用中,实时通信往往是提供无缝用户体验的关键,尤其是在消息、通知、实时更新等应用中。WebSockets 是一种通过单个长期连接提供全双工通信通道的协议。在本文中,我们将学习如何使用 WebSockets 在 React 前端和 Python 后端之间建立 WebSocket 连接,以及如何发送令牌进行授权。
在 React 中设置 WebSocket
React 常用于构建现代 Web 应用程序。要建立 WebSocket 连接,我们可以使用原生 WebSocket API 或像 socket.io-client
这样的库(封装了 WebSocket)。在本节中,我们将使用原生 WebSocket API。
1. 安装依赖项
如果您使用的是支持 WebSocket 的后端,如 Python 中的 FastAPI,那么除了内置的 WebSocket 类外,我们不需要 React 中的其他库。不过,我们可以使用 socket.io 来获得更多功能,这将在后面进行说明。
2. React 中的 WebSocket 连接
要设置 WebSocket 连接,请使用服务器的 URL 创建 WebSocket 对象。操作方法如下:
import React, { useState, useEffect } from "react";
function App() {
const [messages, setMessages] = useState([]);
const [socket, setSocket] = useState(null);
useEffect(() => {
// 连接到 WebSocket 服务器
const ws = new WebSocket("ws://localhost:8000/ws/chat");
ws.onopen = () => {
console.log("WebSocket connection established");
};
ws.onmessage = (event) => {
setMessages((prevMessages) => [...prevMessages, event.data]);
};
ws.onclose = () => {
console.log("WebSocket connection closed");
};
ws.onerror = (error) => {
console.log("WebSocket error: ", error);
};
setSocket(ws);
// 组件卸载时清理
return () => {
ws.close();
};
}, []);
const sendMessage = (message) => {
if (socket) {
socket.send(message);
}
};
return (
<div>
<h1>WebSocket in React</h1>
<div>
<button onClick={() => sendMessage("Hello from React!")}>
Send Message
</button>
</div>
<div>
<h2>Received Messages:</h2>
{messages.map((msg, index) => (
<p key={index}>{msg}</p>
))}
</div>
</div>
);
}
export default App;
- 当组件挂载时,
useEffect
hook 用于创建 WebSocket 连接。 ws.onmessage
事件处理程序用于处理来自服务器的消息。sendMessage
用于向 WebSocket 服务器发送数据。
使用 FastAPI 在 Python 中设置 WebSocket
FastAPI 是使用 Python 构建实时 WebSocket 应用程序的绝佳选择。FastAPI 内置对 WebSocket 的支持,让您可以轻松处理 WebSocket 连接。
1. 安装依赖项
运行 WebSocket 服务器需要 FastAPI 和 ASGI 服务器(如 uvicorn)。
pip install fastapi uvicorn
2. 带 Token 授权的 WebSocket 服务器
让我们使用 FastAPI 在 Python 中创建一个 WebSocket 服务器。在此示例中,我们将处理 WebSocket 连接、发送和接收消息以及使用令牌进行授权。
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Depends, HTTPException
from pydantic import BaseModel
app = FastAPI()
# 依赖项根据 token 获取当前用户
# 更改逻辑以验证 token
def get_current_user(token: str):
if token != "valid-token":
raise HTTPException(status_code=401, detail="Invalid token")
return {"username": "test_user"}
# WebSocket 路由
@app.websocket("/ws/chat")
async def websocket_endpoint(websocket: WebSocket, token: str):
# 使用 token 进行身份验证
try:
current_user = get_current_user(token)
except HTTPException:
await websocket.close(code=1000) # 如果未授权,则关闭连接
return
await websocket.accept()
while True:
try:
message = await websocket.receive_text()
print(f"Received message: {message} from {current_user['username']}")
await websocket.send_text(f"Message received: {message}")
except WebSocketDisconnect:
print(f"Client {current_user['username']} disconnected")
break
这里:
- get_current_user 函数模拟令牌验证(在实际应用中,您需要根据数据库或身份验证服务验证令牌)。
- 在 WebSocket 端点 /ws/chat 中,我们接受 WebSocket 连接并持续监听来自客户端的消息。
WebSocket 连接中的 Token 授权
在典型的 WebSocket 通信中,没有内置机制在建立连接后发送标头(如授权标头)。但是,您仍然可以使用查询参数或子协议在 WebSocket 连接中发送用于授权的令牌。
1. 使用查询参数
一种常见的方式是将令牌作为 WebSocket URL 的一部分发送:
const token = “your_jwt_token” ;
const ws = new WebSocket ( `ws://localhost:8000/ws/chat?token= ${token} ` );
在这种情况下,令牌作为查询参数传递,您可以使用 FastAPI 在服务器端检索它:
from fastapi import Request
@app.websocket("/ws/chat")
async def websocket_endpoint(websocket: WebSocket, request: Request):
token = request.query_params.get('token')
current_user = get_current_user(token)
#其余代码与上面的代码相同
2. 使用子协议
另一种方法是在 WebSocket 握手的子协议标头中发送令牌,服务器可在 WebSocket 连接设置过程中访问该标头:
const token = "your_jwt_token";
const ws = new WebSocket("ws://localhost:8000/ws/chat", token);
在服务器端,您可以按如下方式检索令牌:
@app.websocket("/ws/chat")
async def websocket_endpoint(websocket: WebSocket):
token = websocket.headers.get("Sec-WebSocket-Protocol")
current_user = get_current_user(token)
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Depends, HTTPException
from pydantic import BaseModel
app = FastAPI()
# 依赖项,根据 token 获取当前用户
# 更改逻辑以验证 token
def get_current_user(token: str):
if token != "valid-token":
raise HTTPException(status_code=401, detail="Invalid token")
return {"username": "test_user"}
# WebSocket 路由
@app.websocket("/ws/chat")
async def websocket_endpoint(websocket: WebSocket, token: str):
# 使用 token 进行身份验证
try:
token = websocket.headers.get("Sec-WebSocket-Protocol")
current_user = get_current_user(token)
except HTTPException:
await websocket.close(code=1000) # 如果未经授权则关闭连接
return
# 在 websocket.accept()函数中提供 token,因为 token 是
# 附加子协议的一部分,服务器必须接受该子协议才能发送数据
# 以响应客户端,否则响应客户端将无法接收数据。
await websocket.accept(token)
while True:
try:
message = await websocket.receive_text()
print(f"Received message: {message} from {current_user['username']}")
await websocket.send_text(f"Message received: {message}")
except WebSocketDisconnect:
print(f"Client {current_user['username']} disconnected")
break
结论
在本文中,我们介绍了如何使用 FastAPI 在 React 前端和 Python 后端建立 WebSocket 连接。我们还讨论了如何通过 WebSocket 连接发送授权令牌。
通过将 WebSocket 与基于令牌的身份验证(例如 JWT)相结合,您可以确保只有授权用户才能访问实时功能,使其适用于聊天服务、实时通知和协作工具等应用程序。
请记住,基于令牌的身份验证有助于保护您的 WebSocket 连接并避免未经授权访问敏感数据,即使在实时场景中也是如此。
作者:R. Gupta
本文来自作者投稿,版权归原作者所有。如需转载,请注明出处:https://www.nxrte.com/jishu/im/54737.html