Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
426 views
in Technique[技术] by (71.8m points)

Django Channels long running consumer authentication issues

When using django channels, I have a long-running websocket connection. My users may become logged out due to their session expiring while this connection is still active. This causes sporadic behavior where HTTP requests don't work, because they're not authenticated, but the websocket is still sending and receiving data like nothing is wrong.

The Django Channels docs say:

If you are using a long running consumer, websocket or long-polling HTTP it is possible that the user will be logged out of their session elsewhere while your consumer is running. You can periodically use get_user(scope) to be sure that the user is still logged in.

However, this doesn't work. When I call the following code I'm able to see that Django Channels believes the user is still authed.

user = async_to_sync(get_user)(self.scope)
print(user.is_authenticated)

What is the correct way to check if a user is still authenticated in a Django Channels websocket consumer? This GitHub issue touches on the issue but doesn't have a good solution

Websocket consumer as follows:

class GUIConsumer(WebsocketConsumer):
    def connect(self):
        async_to_sync(self.channel_layer.group_add)(
            GROUP_NAME, self.channel_name)

        user = self.scope.get('user')

        if user and user.has_perm('auth.can_access_ui'):
            self.accept()
        else:
            self.accept()
            self.close()

    def disconnect(self, close_code):
        async_to_sync(self.channel_layer.group_discard)(
            GROUP_NAME, self.channel_name)

    def data(self, event):
        publisher_type = event.get('publisher')
        data = event.get('data')
        self.send(text_data=json.dumps({publisher_type: data})

    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json.get('message', '')
        if message == "---ping---":
            self.send(text_data=json.dumps({'heartbeat': '---pong---'}))
question from:https://stackoverflow.com/questions/65907597/django-channels-long-running-consumer-authentication-issues

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

In the meantime, I'm setting up a recurring javascript HTTP call that checks if the user is still authenticated. If the user is not authenticated I will force a page refresh which will redirect them to the login screen. This works fine, in my use case, because there's no risk of (and no reward for) my internal-only users tampering with my front end. However, this doesn't work if your code is running in a more public setting.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...