使用令牌身份验证时如何对 django 通道中的 websocket 连接中的用户进行身份验证 [重复]

2023-11-29

我正在使用前端框架(Vuejs) and django-rest-framework对于我的项目中的 REST API。另外,对于 JSON Web 令牌身份验证,我正在使用django-rest-framework-jwt。成功登录后,用户将获得一个令牌。该令牌会传递到每个请求中以获取任何与 API 相关的内容。

现在我想整合Django 频道进入我的项目。因此,成功登录后,当客户端收到令牌时,我想发起一个 websocket 连接。然后在服务器(消费者)上,我想检查请求的用户是否不是匿名的。如果请求的用户是匿名的,我想关闭连接或接受它。

这就是我到现在为止的情况:

客户端:

const socket = new WebSocket("ws://" + "dev.site.com"+ "/chat/");

路由.py:

channel_routing = [
    route("websocket.connect", ws_connect),
    ...
    ...
]

消费者:

def ws_connect(message):

    # if the user is no anonymous
    message.reply_channel.send({
        "accept": True
    })

    # else
    message.reply_channel.send({
        "close": True
    })

In the 文档有一个装饰器@channel_session_user_from_http这将提供一个message.user。但我使用的是令牌而不是会话。使用令牌身份验证时如何检查连接上的用户,以便我可以接受或关闭连接。或者,如果有更好的方法,请您告诉我。谢谢。


问题是浏览器不支持在 websocket 升级时传递 jwt auth 标头,所以基本上就是这样。我前段时间遇到了这个问题,并提出了通过查询参数传递令牌的解决方案 - 请注意如果没有 TLS,这是完全不安全的当您在 URI 中公开身份验证时。我无法再访问确切的代码,但想法如下:

from channels.generic.websockets import JsonWebsocketConsumer
from channels.handler import AsgiRequest

from rest_framework_jwt.serializers import VerifyJSONWebTokenSerializer
from jwt.exceptions import InvalidTokenError
from rest_framework.exceptions import ValidationError

class Consumer(JsonWebsocketConsumer):

    def connect(self, message, **kwargs):
        # construct a fake http-like request object from the message
        message.content.setdefault('method', 'FAKE')
        request = AsgiRequest(message)
        # validate the token
        try:
            VerifyJSONWebTokenSerializer().validate(request.GET)
            super().connect(message, **kwargs)
        except (KeyError, InvalidTokenError, ValidationError,):
            # token is either not available or invalid
            # so we disconnect the user
            message.reply_channel.send({'close': True})

向消费者注册

channel_routing = [
    ...
    route_class(Consumer, path=r'^my-ws-endpoint$'),
]

在浏览器端,您可以通过将令牌作为 websocket URI 中的查询参数传递来建立 websocket 连接:

let token: string = 'my-token'; // get the token
let wsHandler: $WebSocket = new $WebSocket('wss://example.com/my-ws-endpoint/?token=' + token, ...);

然后,您可以在类似于以下的装饰器中提取身份验证检查代码@channel_session_user_from_http只需装饰您的连接例程,或者如果您使用基于类的路由,则将代码提取到 mixin 中。

我想重申一下,如果不使用加密,这种方法是完全不安全的,因此在生产中,您的 URI 应该以https/wss.


Edit: 这里有一个相当不错的解决方案用于 DRF 令牌身份验证,适用于基于函数和基于类的路由。它的方法与我的方法几乎相同,构造一个请求对象并将其传递给身份验证器。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用令牌身份验证时如何对 django 通道中的 websocket 连接中的用户进行身份验证 [重复] 的相关文章

随机推荐