사용자가 로그인이 성공되었을 경우 사용자는 서버에게 JWT 토큰을 받게 된다. 기본적으로 서버는 무상태 상태인데, 사용자가 로그인을 요구해야 하는 기능을 사용하게 될 때 request의 header에 토큰을 함께 보내주면 서버는 토큰을 읽어줘야 한다. 토큰을 읽을 때 파이썬 데코레이터를 사용하면 간단하게 혜결이 가능하다. 즉 서버 입장에서는 토큰을 읽어 무상태 상태를 혜결한다.
직역하면 "장식하다"라는 의미로 무엇인가를 장식하는 것이다. 즉 쉽게 말해 본래의 함수가 실행하기 전에 데이 레이터 함수가 먼저 실행한 뒤 본래의 함수가 실행되는 구조이다. westagram 프로젝트에서는 인가를 요구하는 기능에 인가를 확인해 주는 데코레이터를 만들어 먼저 실행하고 그다음 본래의 기능의 함수가 실행한다. 사용하는 방법은 간단하다. decorator 사용하는 함수는 함수의 이름 앞에 @를 붙여서 적용하고자 하는 함수 정의 부분 위에 지정해 주면 된다.
def decorator1(func):
def wrapper():
print('decorator1')
func()
return wrapper
def decorator2(func):
def wrapper():
print('decorator2')
func()
return wrapper
@decorator1
@decorator2
def hello():
print('hello')
hello()
#실행 결과
decorator1
decorator2
hello
상위 간단한 코드를 예를 들어 보겠다. 실행 결과를 보면 hello라는 함수가 실행시켰지만 파이썬은 위에서 아래로 코드가 실행되는 로직을 갖고 있기 때문에 decorator1이 실행되고 decorator2가 실해되고 hello 함수가 실행된다.
데코레이터를 쉽게 불러오기 위해서 새로운 앱을 생성한뒤 앱 내부에 utils.py파일안에 데코레이터 함수를 작성한다.
#필요한 모듈을 불러온다.
from django.http.response import JsonResponse
from users.models import User
from my_settings import SECRET_KEY
from django.core.exceptions import ObjectDoesNotExist
import jwt
필자는 보안을 위해서 SECRET KEY를 새로운 파일을 만들어서 따로 저장해두었기 때문에 임포트해주었다.
def token_reader(func):
def wrapper(self, request, *args, **kwargs):
try:
token = request.headers.get('Authorization', None)
payload = jwt.decode(token, SECRET_KEY, algorithms='HS256')
user = User.objects.get(id=payload['id'])
request.user = user
except jwt.exceptions.DecodeError:
return JsonResponse({'message' : 'INVALID_TOKEN' }, status=400)
except User.DoesNotExist:
return JsonResponse({'message' : 'INVALID_USER'}, status=400)
return func(self, request, *args, **kwargs)
return wrapper