How to get current user from a Django Channels web socket packet?

user1577434 picture user1577434 · Oct 12, 2016 · Viewed 9.8k times · Source

I was following this tutorial: Finally, Real-Time Django Is Here: Get Started with Django Channels.

I wanted to extend the app by using Django User objects instead of the handle variable. But how can I get the current user from the received WebSocket packet in my ws_recieve(message) function?

I noticed that both the csrftoken and the first ten digits of sessionid from the web socket packet match a normal HTTP request. Can I get the current user with this information?

For reference the received packet looks like this:

{'channel': <channels.channel.Channel object at 0x110ea3a20>,
 'channel_layer': <channels.asgi.ChannelLayerWrapper object at 0x110c399e8>,
 'channel_session': <django.contrib.sessions.backends.db.SessionStore object at 0x110d52cc0>,
 'content': {'client': ['127.0.0.1', 52472],
             'headers': [[b'connection', b'Upgrade'],
                         [b'origin', b'http://0.0.0.0:8000'],
                         [b'cookie',
                          b'csrftoken=EQLI0lx4SGCpyTWTJrT9UTe1mZV5cbNPpevmVu'
                          b'STjySlk9ZJvxzHj9XFsJPgWCWq; sessionid=kgi57butc3'
                          b'zckszpuqphn0egqh22wqaj'],
                         [b'cache-control', b'no-cache'],
                         [b'sec-websocket-version', b'13'],
                         [b'sec-websocket-extensions',
                          b'x-webkit-deflate-frame'],
                         [b'host', b'0.0.0.0:8000'],
                         [b'upgrade', b'websocket'],
                         [b'sec-websocket-key', b'y2Lmb+Ej+lMYN+BVrSXpXQ=='],
                         [b'user-agent',
                          b'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) '
                          b'AppleWebKit/602.1.50 (KHTML, like Gecko) Version'
                          b'/10.0 Safari/602.1.50'],
                         [b'pragma', b'no-cache']],
             'order': 0,
             'path': '/chat-message/',
             'query_string': '',
             'reply_channel': 'websocket.send!UZaOWhupBefN',
             'server': ['127.0.0.1', 8000]},
 'reply_channel': <channels.channel.Channel object at 0x110ea3a90>}

Answer

HassenPy picture HassenPy · Oct 12, 2016

Note: The question is specific to Channels 1.x and the Django session system, if you're here for Channels 2.x way, please read the docs from the link below, they're more than clear on how to do this, the Channels 1.x docs were confusing for some people (including me), this is why this question and others were made, the Channels 2.x docs are crystal clear on how to achieve this:
https://channels.readthedocs.io/en/latest/topics/authentication.html#django-authentication


Channels 1.x:

You can get access to a user and http_session attributes of your message by changing the decorators in consumers.py to match the docs:

You get access to a user’s normal Django session using the http_session decorator - that gives you a message.http_session attribute that behaves just like request.session. You can go one further and use http_session_user which will provide a message.user attribute as well as the session attribute.

so the consumers.py file in the example should become the following:

from channels.auth import http_session_user, channel_session_user, channel_session_user_from_http  

@channel_session_user_from_http  
def ws_connect(message):  
    ...  
    ...


@channel_session_user  
def ws_receive(message):  
    # You can check for the user attr like this  
    log.debug('%s', message.user)  
    ...  
    ...  


@channel_session_user  
def ws_disconnect(message):  
    ...  
    ...  

Notice the decorators change.
Also, i suggest you don't build anything upon that example

for more details see: https://channels.readthedocs.io/en/1.x/getting-started.html#authentication