로그인을 시켜주는 함수 login (이하 login) 과
django.contrib.auth.login
def login(request, user, backend=None):
"""
Persist a user id and a backend in the request. This way a user doesn't
have to reauthenticate on every request. Note that data set during
the anonymous session is retained when the user logs in.
"""
로그인 정보를 확인하는 미들웨어 AuthenticationMiddleware (이하 authentication) 의 콜라보
django.contrib.auth.middleware.AuthenticationMiddleware
class AuthenticationMiddleware(MiddlewareMixin):
def process_request(self, request):
...
request.user = SimpleLazyObject(lambda: get_user(request))
login 은 인자로 넘어온 request 객체에서 session 을 가져와서 인증에 활용한다.
request.session
session 은 기본적으로 settings 에 설정된 SESSION_ENGINE 에 따라서, db, cache, file, signedcookie 등등을 활용한다.
디폴트 값은 db 이다. 'django.contrib.sessions.backends.db'
db 에 저장될 때 session 은 아래와 같은 필드 구성을 가진다.
id
session_key
created_at
user_id
user_id 와 매칭되는 session_key 를 DB 에 저장해서, session_key 를 클라이언트에 cookie 로 저장하여, 유저 활동의 연속성을 보장하는 것.
created_at 은 session 만료 기준을 통해, db 에 존재하는 session 값이라도 유효하지 않다고 판단하게 해준다.
AbstractUser 를 상속받은 user 에서 사용할 수 있는 get_session_auth_hash 함수를 통해서 session_key 를 가져올 수 있다.
def login(request, user, backend=None):
...
if hasattr(user, "get_session_auth_hash"):
session_auth_hash = user.get_session_auth_hash()
session_key, hash_session_key, backend_session_key 를 나눠서 session 에 등록해준다.
이게 로그인이다.
def login(request, user, backend=None):
...
request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
request.session[BACKEND_SESSION_KEY] = backend
request.session[HASH_SESSION_KEY] = session_auth_hash
이제 저장된 session 값을 활용하는 걸 보자.
class AuthenticationMiddleware(MiddlewareMixin):
def process_request(self, request):
...
request.user = SimpleLazyObject(lambda: get_user(request))
django.contrib.auth.middleware
의 get_user
를 활용한다.
login 에서 세팅해준 session 값들을 이용해서 user 를 찾는다.
def get_user(request):
try:
# request.session[SESSION_KEY] 사용
user_id = _get_user_session_key(request)
# request.session[BACKEND_SESSION_KEY] 사용
backend_path = request.session[BACKEND_SESSION_KEY]
except KeyError:
pass
...
if hasattr(user, "get_session_auth_hash"):
# request.session[HASH_SESSION_KEY] 사용
session_hash = request.session.get(HASH_SESSION_KEY)
...
return user or AnonymousUser()
다만 이 과정을 매 요청마다 하는 건 아니고, SimpleLazyObject 를 통해서, request.user 가 호출되어 사용될 때만 get_user 를 통해서 위 과정을 거친다.
class AuthenticationMiddleware(MiddlewareMixin):
def process_request(self, request):
...
request.user = SimpleLazyObject(lambda: get_user(request))