import logging import os from channels.auth import AuthMiddlewareStack from channels.db import database_sync_to_async from channels.routing import ProtocolTypeRouter, URLRouter from django.contrib.auth.models import AnonymousUser from django.core.asgi import get_asgi_application from rest_framework.authtoken.models import Token from console.routing import websocket_urlpatterns _log = logging.getLogger(__name__) os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'console.settings.dev') django_asgi_app = get_asgi_application() class TokenHeaderAuthMiddleware: """Middleware для авторизации WebSocket с помощью токена в header. Будет вызываться в последнюю очередь и только после неуспешной попытки аутентификации по сессии, т.е. если scope['user'] == AnonymousUser() Пример: Authorization: Token vgft67uhgtreerfcgvh678uihvhkugct7iyukv """ def __init__(self, inner): self.inner = inner async def __call__(self, scope, receive, send): headers = dict(scope['headers']) if b'authorization' in headers and scope['user'] == AnonymousUser(): token_name, token_key = headers[b'authorization'].decode().split() if token_name == 'Token': user = await self.get_user_by_token(token_key) if user: scope['user'] = user return await self.inner(scope, receive, send) return await self.inner(scope, receive, send) @database_sync_to_async def get_user_by_token(self, token): try: return Token.objects.get(key=token).user except Token.DoesNotExist: return application = ProtocolTypeRouter( { "websocket": AuthMiddlewareStack(TokenHeaderAuthMiddleware(URLRouter(websocket_urlpatterns))) } )