[realtime_auction] django channels에서 jwt middleware오류

yoon·2023년 9월 25일

realtime_auction

목록 보기
3/3

🔎 django-channels에서 jwt를 사용하려면 middleware를 작성하고, 프로젝트 폴더 안에 있는 asgi.py에서 인증 방법을 설정해줘야한다. 하지만 내가 작성한 middleware를 사용하면 계속 웹소켓 연결이 끊어진다.

❌ 문제

# auction/middlewares.py
class WebSocketJWTMiddleware:
	def __init__(self,app):
    	self.app = app
    async def __call__(self, scope, receive, send):
    	...
        ...
        return self.app(scope, receive, send)

다음과 같은 파일을 작성하면 connect함수를 실행하기 전에 middlewares의 call함수를 동작시킨다. 이때 함수에 포함된 print문은 모두 동작 후 웹소켓이 끊어지는 것으로 보아 return 값에 문제가 있다고 판단하였다.

✅ 해결방법

channels에서 제공하는 BaseMiddleware를 상속받아 사용한다.

# auction/middlewares.py
from channels.middleware import BaseMiddleware

@database_sync_to_async
def get_user(user_id):
    try:
        return User.objects.get(id=user_id)
    except User.DoesNotExist:
        return AnonymousUser()
        
class WebSocketJWTAuthMiddleware(BaseMiddleware)::
    def __init__(self, inner):
        self.inner = inner

    async def __call__(self, scope, receive, send):
        authorization_header = next(
            (header for header in scope["headers"] if header[0] == b"cookie"), None
        )
        
        if authorization_header:
            token = (
                authorization_header[1].decode("utf-8").split("=")[-1]
            )
        else:
            token = None

        try:
            access_token = AccessToken(token)
            scope["user"] = await get_user(access_token["user_id"])
        except TokenError:
            scope["user"] = AnonymousUser()

        print("user : ", scope["user"])

        return await super().__call__(scope, receive, send)

🔎 설정 방법

#config/asgi.py
import auction.routing

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

auction.routing에 설정한 웹소켓 url을 직접 작성한 middleware로 감싸주면, 웹소켓을 연결하기 전에 JWT 인증 방법을 사용할 수 있다.

profile
하루하루 차근차근🌱

0개의 댓글