Каналы Django 2: два метода аутентификации - PullRequest
0 голосов
/ 14 мая 2019

Как я могу реализовать несколько методов аутентификации для моего приложения каналов Django? Я имею в виду, у меня есть авторизация на основе токена и AuthMiddlewareStack.

Как я могу поддерживать эти две аутентификации для управления аутентификацией django в сеансе для моего внутреннего потребителя данных websocket приложения / notify / etc ... и принять аутентификацию токена websocket для сторонних приложений?

Вот мой routing.py:

application = ProtocolTypeRouter({
    # (http->django views is added by default)
    'websocket': AuthMiddlewareStack(
        URLRouter(
            app.routing.websocket_test
        )
    ),
    "websocket": TokenAuthMiddlewareStack(
        URLRouter([
            app.routing.websocket_test
        ]),
    )
})

Спасибо.

1 Ответ

0 голосов
/ 17 мая 2019

Я решил проблему, реализуя стек промежуточного программного обеспечения универсальной аутентификации, документы Django Channels, в этих примерах не хватает.

В любом случае, я реализовал гибридный стек аутентификации, который поддерживает: Session,Методы заголовка токена и аутентификации URL-адреса токена работают без сбоев:

WSTokenAuthMiddleware.py:

from urllib.parse import parse_qs

from channels.auth import AuthMiddlewareStack
from django.utils import timezone

from rest_framework.authtoken.models import Token
from django.contrib.auth.models import AnonymousUser
from django.db import close_old_connections


class WSTokenAuthMiddleware:
    """
    Token [Querystring/Header] authorization middleware for Django Channels 2
    """

    def __init__(self, inner):
        self.inner = inner

    def __call__(self, scope):
        query_string = parse_qs(scope['query_string']) #Used for querystring token url auth
        headers = dict(scope['headers']) #Used for headers token url auth
        if b'token' in query_string:
            try:
                token_key = query_string[b'token'][0].decode()
                token = Token.objects.get(key=token_key)
                scope['user'] = token.user
                close_old_connections()
            except ApiToken.DoesNotExist:
                scope['user'] = AnonymousUser()
        elif b'authorization' in headers:
            try:
                token_name, token_key = headers[b'authorization'].decode().split()
                if token_name == 'Token':
                    token = Token.objects.get(key=token_key)
                    scope['user'] = token.user
                    close_old_connections()
            except ApiToken.DoesNotExist:
                scope['user'] = AnonymousUser()
        else:
            pass #Session auth or anonymus

        return self.inner(scope)

UniversalAuthMiddlewareStack = lambda inner: WSTokenAuthMiddleware(AuthMiddlewareStack(inner))

Routing.py:

application = ProtocolTypeRouter({
    "websocket": UniversalAuthMiddlewareStack(
        URLRouter(
            ...
        ),
    ),
})
...