We want to use django-channels for our websockets but we need to authenticate as well. We have a rest api running with django-rest-framework and there we use tokens to authenticate a user, but the same functionality does not seem to be built into django-channels.
相关问题
- Django Attribute error 'datetime.timedelta'
- Uploading multiples image with Django Rest Framewo
- How do I mock a third party library inside a Djang
- Nginx with Daphne gives 502 Bad Gateway
- Django serializers vs rest_framework serializers
相关文章
- Django/Heroku: FATAL: too many connections for rol
- Serialise choice text for IntegerField with choice
- Django Rest Framework custom response message
- Django REST Framework - OAuth2 Consumer API from e
- Django Rest Framework Without Database
- Django Rest Framework - AssertionError Fix your UR
- Django rest framework nested viewsets and routes
- How can I use pagination_class in django-rest-fram
For Django-Channels 2 you can write custom authentication middleware https://gist.github.com/rluts/22e05ed8f53f97bdd02eafdf38f3d60a
token_auth.py:
routing.py:
I believe sending token in query string can expose token even inside HTTPS protocols. To come around such issue I have used the following steps:
Create a token based REST API endpoint which creates temporary session and respond back with this
session_key
(This session is set to expire in 2 minutes)Use this
session_key
in query parameter in channels parameterI understand there is one extra API call but I believe it's much more secure than sending token in URL string.
Edit: This is just another approach to this problem, as discussed in comments, get parameters are exposed only in urls of http protocols, which should be avoided in anyhow.
This answer is valid for channels 1.
You can find all information in this github issue: https://github.com/django/channels/issues/510#issuecomment-288677354
I will summarise the discussion here.
copy this mixin into your project: https://gist.github.com/leonardoo/9574251b3c7eefccd84fc38905110ce4
apply the decorator to
ws_connect
the token is received in the app via an earlier authentication request to the
/auth-token
view in django-rest-framework. We use a querystring to send the token back to django-channels. If you're not using django-rest-framework you can consume the querystring in your own way. Read the mixin for how to get to it.has_permission()
implemented on theUser
model, so it can just check its instance. If there is no token or the token is invalid, there will be no user on the message.thanks to github user leonardoo for sharing his mixin.
Regarding Channels 1.x
As already pointed out here the mixin by leonardoo is the easiest way: https://gist.github.com/leonardoo/9574251b3c7eefccd84fc38905110ce4
I think, however, it is somewhat confusing to figure out what the mixin is doing and what not, so I will try to make that clear:
When looking for a way to access message.user using the native django channels decorators you would have to implement it like this:
Channels does that by authenticating the user, creating a http_session and then converting the http_session in a channel_session, which uses the reply channel instead of cookies to identify the client. All this is done in channel_session_user_from_http. Have a look at the channels source code for more detail: https://github.com/django/channels/blob/1.x/channels/sessions.py
leonardoo's decorator rest_token_user does, however, not create a channel session it simply stores the user in the message object in ws_connect. As the token is not sent again in ws_receive and the message object is not available either, in order to get the user in ws_receive and ws_disconnect as well, you would have to store it in the session yourself. This would be a easy way to do this:
The following Django-Channels 2 middleware authenticates JWTs generated by djangorestframework-jwt .
The token can be set via the djangorestframework-jwt http APIs, and it will also be sent for WebSocket connections if
JWT_AUTH_COOKIE
is defined.settings.py
routing.py:
json_token_auth.py