我在我的项目中使用REST API的前端框架(Vuejs)和django-rest-framework。另外,对于JSON Web令牌身份验证,我正在使用django-rest-framework-jwt。成功登录后,将为用户提供令牌。此令牌传递到每个请求中,以获取与API相关的所有内容。
现在,我想将Django频道集成到我的项目中。因此,成功登录后,当在客户端收到令牌时,我想启动一个websocket连接。然后在服务器(消费者)上,我想检查所请求的用户是否不是匿名的。如果请求的用户是匿名用户,我想关闭连接或接受它。
这是我到目前为止的方法:
客户端:
const socket = new WebSocket("ws://" + "dev.site.com"+ "/chat/");
routing.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
})
在文档中有一个装饰器@channel_session_user_from_http
,它将提供一个message.user
。但是我使用令牌而不是会话。使用令牌身份验证时,如何检查用户的连接,以便我可以接受或关闭连接。或者,如果有更好的方法,请告诉我。谢谢。
问题在于浏览器不支持在websocket升级中传递jwt auth标头,基本上就是这样。我前段时间遇到了这个问题,并提出了通过查询参数传递令牌的解决方案-请注意,在TLS中公开身份验证时,如果没有TLS,这是完全不安全的。我无法再访问确切的代码,但是这里有个主意:
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, ...);
然后,您可以在类似于装饰器的装饰器中提取auth检查代码,@channel_session_user_from_http
并仅装饰您的连接例程;如果使用基于类的路由,则可以将代码提取到mixin。
我想重复一遍,尽管这种方法在不使用加密的情况下是完全不安全的,所以在生产中,URI应该以开头https/wss
。
编辑:这是DRF令牌身份验证的不错的解决方案,适用于基于函数和基于类的路由。它具有与我的方法几乎相同的方法,即构造一个请求对象并将其传递给身份验证器。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句