본문 바로가기

내일배움 캠프/TIL

django-channels middleware custom

Django Channels는 Django 웹 프레임워크를 확장하여 WebSocket 및 비동기 작업을 지원하는 패키지입니다. Middleware는 Django Channels에서 HTTP 요청 및 WebSocket 연결과 같은 모든 요청에 대한 중간 처리를 담당하는 기능입니다.

Django Channels의 Middleware는 다음과 같은 역할을 수행합니다:

프로토콜 업그레이드(Protocol Upgrade) 지원
인증 및 사용자 추적
권한 부여
데이터 변환 및 중개
에러 처리
성능 및 보안

 

이를 위해서 channels에서 user를 찾기위해 middleware를 사용했는데 기본 channels에서는 jwt token으로 유저를 찾을수있는 middleware가 없어서 custom을 통해서 jwt token을 이용해서 user를 찾는 middleware를 구할수있었습니다

@database_sync_to_async
def get_user(validated_token):
    try:
        user = get_user_model().objects.get(id=validated_token["user_id"])

        return user

    except User.DoesNotExist:
        return AnonymousUser()


class JwtAuthMiddleware(BaseMiddleware):
    def __init__(self, inner):
        self.inner = inner

    async def __call__(self, scope, receive, send):
        close_old_connections()
        token = parse_qs(scope["query_string"].decode("utf8"))["token"][0]
        try:
            UntypedToken(token)
        except (InvalidTokenError, TokenError) as e:
            return None
        else:
            decoded_data = jwt_decode(token, settings.SECRET_KEY, algorithms=["HS256"])
            scope["user"] = await get_user(validated_token=decoded_data)
        return await super().__call__(scope, receive, send)


def JwtAuthMiddlewareStack(inner):
    return JwtAuthMiddleware(AuthMiddlewareStack(inner))

JwtAuthMiddleware를 이용해서 asgi.py에 import를 하게되면  

import os
import django
from django.core.asgi import get_asgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BFFs.settings")
django.setup()

from channels.routing import ProtocolTypeRouter, URLRouter
from .middleware import JwtAuthMiddlewareStack
from alarm import routing

application = ProtocolTypeRouter(
    {
        "http": get_asgi_application(),
        "websocket": JwtAuthMiddlewareStack(
            URLRouter(routing.websocket_urlpatterns),
        ),
    }
)

jwt token을 이용해서 user를 찾아낼수있게됩니다. 

시간이 부족한 이슈로 쿼리스트링으로 보냈지만 시간이 조금더 넉넉했다면 헤더로 token을 보내서 받은 후 decode를 하는 과정을 수행하는 코드로 바꿀거같습니다