π μ λ² ν¬μ€ν μ channels μΈμ¦μ κ΄ν κΈμ μΌλ€.
νμ§λ§ μ€μ ν μ€νΈλ₯Ό ν΄λ³΄λ λ΄κ° μνλ μ¬μ©μλ‘ μΈμ¦μ΄ λμ§ μμμλ€.
μ§κΈλΆν° νλμ© λ―μ΄λ³΄λ €κ³ νλ€.class ChatConsumer(AsyncWebsocketConsumer): async def connect(self): # λ‘κ·ΈμΈλ μ¬μ©μμΈμ§ νμΈ if self.scope['user']: pass else: self.close() await self.accept()
λλ μμκ°μ΄ κ°λ¨νκ² scopeμ λ΄κΈ΄ userλ₯Ό νμΈνμ¬ μΈμ¦ μνμ ν μ€νΈ νλ€.
ν μ€νΈλ₯Ό μννλλ° κ³μ ν μ¬μ©μμ μ λ³΄λ§ λ€μ΄μλ€. μ΄κ² μμνμ¬ scope dataμ°μ΄λ΄€λ€.{'asgi': {'version': '3.0'}, 'client': ['127.0.0.1', 54699], 'cookies': {'csrftoken': 'FFQG53vwTjHdfsPEkHyF3iu24FHSdq4M27yVrDV8IXeW2fIxzI2gOu1yRckbU5VT', 'sessionid': 'mccrs5c1rk52kdibw1l469tak3x2elnv'}, 'headers': [(b'host', b'127.0.0.1:8000'), (b'connection', b'Upgrade'), (b'pragma', b'no-cache'), (b'cache-control', b'no-cache'), (b'user-agent', b'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' b' (KHTML, like Gecko) Chrome/106.0.5249.207 Whale/3.17.145.18' b' Safari/537.36'), (b'upgrade', b'websocket'), (b'origin', b'http://127.0.0.1:5500'), (b'sec-websocket-version', b'13'), (b'accept-encoding', b'gzip, deflate, br'), (b'accept-language', b'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7'), (b'cookie', b'csrftoken=FFQG53vwTjHdfsPEkHyF3iu24FHSdq4M27yVrDV8IXeW2fIxzI' b'2gOu1yRckbU5VT; sessionid=mccrs5c1rk52kdibw1l469tak3x2elnv'), (b'sec-websocket-key', b'tF4uRtVXNpr55l9KcDoD8w=='), (b'sec-websocket-extensions', b'permessage-deflate; client_max_window_bits')], 'path': '/ws/socket-server/1/', 'path_remaining': '', 'query_string': b'', 'raw_path': b'/ws/socket-server/1/', 'server': ['127.0.0.1', 8000], 'session': <django.utils.functional.LazyObject object at 0x00000237C83AFD60>, 'subprotocols': [], 'type': 'websocket', 'url_route': {'args': (), 'kwargs': {'room_id': 1}}, 'user': <channels.auth.UserLazyObject object at 0x00000237C83AFB50>}
보면 'user' λΆλΆμ΄
channels.auth.UserLazyObject λ₯Ό μ¬μ©μ€μΈκ²μ μ μ μμλ€.
λ channels.auth μ AuthMiddlesareStack μ μ¬μ©νκ³ μμ΄ ν΄λΉ ν¨μλ‘ λ€μ΄κ°λ³΄μλ€.class AuthMiddleware(BaseMiddleware): """ Middleware which populates scope["user"] from a Django session. Requires SessionMiddleware to function. """ def populate_scope(self, scope): # Make sure we have a session if "session" not in scope: raise ValueError( "AuthMiddleware cannot find session in scope. " "SessionMiddleware must be above it." ) # Add it to the scope if it's not there already if "user" not in scope: scope["user"] = UserLazyObject() async def resolve_scope(self, scope): scope["user"]._wrapped = await get_user(scope) async def __call__(self, scope, receive, send): scope = dict(scope) # Scope injection/mutation per this middleware's needs. self.populate_scope(scope) # Grab the finalized/resolved scope await self.resolve_scope(scope) return await super().__call__(scope, receive, send)
scope ν¨μμ user λ°μ΄ν°λ get_user(scope)λ₯Ό ν΅ν΄ λ°μ΄ν°λ₯Ό κ°μ Έμ€κ³ μμκ³ ν΄λΉ ν¨μλ
@database_sync_to_async def get_user(scope): """ Return the user model instance associated with the given scope. If no user is retrieved, return an instance of `AnonymousUser`. """ # postpone model import to avoid ImproperlyConfigured error before Django # setup is complete. from django.contrib.auth.models import AnonymousUser if "session" not in scope: raise ValueError( "Cannot find session in scope. You should wrap your consumer in " "SessionMiddleware." ) session = scope["session"] user = None try: user_id = _get_user_session_key(session) backend_path = session[BACKEND_SESSION_KEY] except KeyError: pass else: if backend_path in settings.AUTHENTICATION_BACKENDS: backend = load_backend(backend_path) user = backend.get_user(user_id) # Verify the session if hasattr(user, "get_session_auth_hash"): session_hash = session.get(HASH_SESSION_KEY) session_hash_verified = session_hash and constant_time_compare( session_hash, user.get_session_auth_hash() ) if not session_hash_verified: session.flush() user = None return user or AnonymousUser()
μΈμ μ 보λ₯Ό ν΅ν΄μ κ°μ Έμ€κ³ μμ΄μ μ λλ‘ user λ°μ΄ν°λ₯Ό λͺ» κ°μ Έμλ κ²μ΄λ€.
μ΄ λΆλΆμ ν΄κ²°νλ €λ©΄ μ λ² ν¬μ€ν μμ μΈκΈνλ κ² μ²λΌ κ·Όλ³Έμ μΌλ‘ midlewareλ₯Ό λ΄κ° 컀μ€ν ν΄μ μ¬μ©νλ©΄ λλ€.