🔎 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 인증 방법을 사용할 수 있다.