Assignment #1 | Westagram [Mission 6.5] 로그인 인증 데코레이터(decorator)

Jayson Hwang·2022년 5월 21일
0

Westagram Project

목록 보기
7/11
post-thumbnail

1.. Decorator 사용 이유??

통상적으로 웹사이트를 이용할 때, 우리는 최초 로그인을 한 이후부터 여러 권한을 필요로하는 기능을 재로그인 과정없이 사용한다.
사실, HTTP는 "stateless" 특성으로 인하여 이전의 요청이나 응답을 기억하지 못하고 있다. 데코레이터는 "그럼에도 불구하고 내가 로그인을 하여 토큰을 부여받은 사용자인 것을 어떻게 재로그인 과정없이도 인지하고 있는 것인가"에 대한 의문점으로부터 시작된다.

HTTP REQUEST HEADERS

백엔드(서버)에서는 최초 로그인에 성공한 사용자에게 토큰(Token)을 발행하고, 프론트에서는 이 토큰을 Local Storage 또는 Sessiong Storage에 보관한다. 그리고 이 저장된 토큰을 새로운 요청때마다 HTTP request header에 넣어서 보내줌으로써 새로운 인증의 과정을 거치지 않은 채 로그인된 상태로 유지하게 만들어준다.

그리고 이 과정에서 Request header에 포함된 토큰이 유효한지를 확인하기 위해서 로그인 데코레이터(Decorator)를 사용한다.


2..Decorator(데코레이터)

기본적으로, 데코레이터는 특정 함수의 바로 위에 작성되어 특정 함수가 실행되기 전에 먼저 실행되고, 그 과정에서 사전에 처리하고 싶은 작업을 우선적으로 처리하는 함수이다.

토큰으로 권한이 확인되지 않는다면 특정 기능을 담은 함수는 실행되지 않는다.

이번 프로젝트에서 로그인 데코레이터는
users app에 utils.py를 생성하여 작성할 예정

3.. SignIn Decorator

[1] # user/utils.py
 
  	import json
 	import jwt

	from django.http  import JsonResponse
   	from django.conf  import settings
 
	from users.models import User

  	def signin_decorator(func):
[2]   	def wrapper(self, request, *args, **kwargs):
          	try:
[3]           access_token = request.headers.get('Authorization', None)
[4]           payload      = jwt.decode(access_token, settings.SECRET_KEY, algorithms=settings.ALGORITHM)
[5]           user         = User.objects.get(id=payload['id'])
[6]           request.user = user

[7]       	except jwt.exceptions.DecodeError: 
            	return JsonResponse({'message' : 'INVALID_TOKEN'}, status = 400)

[8]       	except User.DoesNotExist: 
            	return JsonResponse({'message' : 'INVALID_USER'}, status = 400)

          	return func(self, request, *args, **kwargs)

      	return wrapper

[1] : 보통 데코레이터를 utils.py 라는 파일에 별도로 저장해서 필요할 때마 import 하여 사용한다. 이번 signin_decorator 함수는 유저 정보와 관련이 있으므로user 디렉토리에 만들어서 저장

[2] : 내부 함수인 wrapper 함수에는 self(instance자신), request(http request)를 매개변수로 받고, 이후 확장성을 고려하여 *args와 **kwargs까지 매개변수로 받는다.
매개변수가 고정되어 있지 않다면, wrapper 함수를 가변인수 함수로 만든다.

[3] : access_token은 HTTP request header 속 Authorization 값을 가져오며, 없을 때는 None으로 값을 넘긴다.

[4] : payload는 토큰을 디코딩(decoding)하면 나오게 될 사용자에 대한 정보
토근 발행 시와 동일한 사용자라면 동일한 payload가 반환되며, 디코딩에 들어가는 SECRET 과 algorithms 은 토큰 발행 시 입력한 정보와 동일해야한다.
(!! decode의 algorithms 주의... 's' 꼭 들어가야함!!)
(!! encode 할 때는 algorithm , decode할 때는 algorithms)

[5] : 데이터베이스에서 토큰 사용자 정보와 매칭되는 사용자 정보를 불러오고, user라는 변수에 저장함. 토큰 발행 시 id키 값으로 사용자 정보를 저장했으므로, 불러올 때도 동일하게 id 키값을 사용.

[6] : request에 user 라는 변수를 지정하여 [5]에서 불러온 유저 정보 객체를 담는다. 이 객체를 데코레이터 다음에 나오는 함수에서 사용!!!!!!

** 토큰 정보를 확인하는 HTTP request에는 토큰을 제외하고 다른 사용자 정보가 전혀 들어오지 않기 때문에, 이 user 값을 request에 저장해서 이후 활용함.

** request는 가변객체이며, 가변 객체이기에 다른 객체 또는 변수 할당이 가능.

[7] : 토큰이 손상되었거나, 전달된 토큰 값이 없을 경우 DecodeError 발생.
즉, 서버에서 발급한 토큰이 아니라면 (시크릿키나 알고리즘 방식이 다르면) decode가 불가하여 발생하는 에러.

[8] : 토큰에서 디코드된 사용자 정보가 데이터베이스에 존재하지 않을 때 DoesNotExist 발생.

profile
"Your goals, Minus your doubts, Equal your reality"

0개의 댓글