好吧,我也遇到了同样的问题。首先,您不能使用 django 频道进行 JWT 身份验证,因为您可以通过频道发送的唯一内容是 query string 并且您不能设置标头参数或诸如 http 协议之类的东西(尤其是如果您使用 @ 987654324@ 作为您的客户端)。出于安全目的,我不想将我的令牌作为查询字符串发送(因为每个人都可以看到它)。所以我在这里解释我的解决方案,也许它也可以解决你的问题。我创建了一个用于在我的套接字中注册的 API,在该 API 中,我返回了一个票据(uuid 类型)作为响应,并且在同一个 API 中,我根据用户缓存了这个票据:
class RegisterFilterAPIView(APIView):
"""
get:
API view for retrieving ticket uuid.
"""
authentication_classes = (JWTAuthentication,)
permission_classes = (IsAuthenticatedOrReadOnly,)
def get(self, request, *args, **kwargs):
ticket_uuid = str(uuid4())
if request.user.is_anonymous:
cache.set(ticket_uuid, False, TICKET_EXPIRE_TIME)
else:
# You can set any condition based on logged in user here
cache.set(ticket_uuid, some_conditions, TICKET_EXPIRE_TIME)
return Response({'ticket_uuid': ticket_uuid})
在这部分之后,我将此票作为查询字符串发送到我的套接字,例如:
var endpoint = 'ws://your/socket/endpoint/?ticket_uuid=some_ticket';
var newSocket = new WebSocket(endpoint);
newSocket.onmessage = function (e) {
console.log("message", e)
};
newSocket.onopen = function (e) {
console.log("open", e);
};
newSocket.onerror = function (e) {
console.log("error", e)
};
newSocket.onclose = function (e) {
console.log("close", e)
};
请注意,上面的代码是用JS写的,所以你应该根据你的要求把它改成别的东西。最后,在我的消费者中,我处理了这张在我的注册 API 中创建的票:
from urllib.parse import parse_qsl
from django.core.cache import cache
from channels.generic.websocket import AsyncJsonWebsocketConsumer
class FilterConsumer(AsyncJsonWebsocketConsumer):
async def websocket_connect(self, event):
try:
query_string = self.scope['query_string'].decode('utf-8')
query_params = dict(parse_qsl(query_string))
ticket_uuid = query_params.get('ticket_uuid')
self.scope['has_ticket'] = cache.get(ticket_uuid)
if not cache.delete(ticket_uuid): # I destroyed ticket for performance and security purposes
raise Exception('ticket not found')
except:
await self.close()
return
await self.accept()
所以现在您有了一个安全的注册 API(如获取令牌 API),您可以根据您的 JWT 令牌生成令牌,但要确保您的服务器支持缓存后端服务。您还可以根据您的票值在您的 websocket 连接方法中设置self.scope['user']。我希望这可以解决您的问题。