django #7 인스타그램 클론 코딩(3) - 로그인 데코레이터

Junyoung Kim·2022년 1월 21일
0

django

목록 보기
7/10

앞선 포스트에서 로그인 시 JWT Token 발급을 해주면, 사용자는 로그인 이후에 추가적인 요청을 보낼때마다 로그인을 해줘야하는 불편한 절차를 없앨 수 있다고 했다. 이것을 인가(Authorization)이라고 한다.

그렇다면 django에서는 어떻게 인가를 구현할까?
답은 파이썬의 중첩 함수 구조인 데코레이터를 이용하는 것이다.

데코레이터(decorator)

데코레이터는 위 사진의 closure처럼 함수 위에 달린 장식(decorator)를 먼저 호출하는 방식이다. 다르게 표현하면 chain of function, 여러개의 함수가 연속적으로 호출이 된다. 다음 과정을 살펴보자.

def func1(func):
    print(1)
    
    def func2():
        print(3)
        
        def func3():
            print(4)
                
            return func
        
        print(3)    
        return func3
        
    print(2)
    return func2

def test():
    print(6)
    
func1(test)()()()
#실행결과
1
2
3
4
5
6

파라미터로 넣은 test가 제일 늦게 실행되고, func1 안에서도 함수 바깥쪽의 print가 먼저 실행되는 것을 볼 수 있다.

이것을 데코레이터의 형태로 바꿔주면 다음과 같다.

@func_1
def test():
	print(6)

데코레이터는 함수 안에 함수가 중첩된 중첩 함수 형태만 적용 가능하다. 그래서 일반적으로 데코레이터 함수 안에 wrapper 함수를 선언해서 만든다.


로그인 데코레이터

우리는 대부분의 회원제 사이트를 이용할 때, 게시물 작성이나 댓글 작성은 회원인 상태에서 가능하다.
다음 포스트에서 다뤄볼 게시물/댓글 작성, 팔로우 및 좋아요는 모두 회원인 상태에서 요청해야 한다.

이것을 위에서 다뤄본 데코레이터를 이용하면, 게시물과 댓글 등등에 관련된 뷰 위에 로그인 데코레이터를 달아 주면 로그인 절차를 생략해도 되는 것이다.

django에서는 보통 로그인 데코레이터를 유저 모델링이 있는 users 앱에 utils.py을 따로 생성해 views.py에 import하는 방법을 사용한다.

# users/utils.py

import jwt, json

from django.http  import JsonResponse

from my_settings  import SECRET_KEY, ALGORITHM             
from users.models import User

def login_decorator(func):
    def wrapper(self, request, *args, **kwargs):				[1]
        try:
            access_token = request.headers.get('Authorization', None)		[2]         
            payload      = jwt.decode(access_token, SECRET_KEY, ALGORITHM)  
            request.user = User.objects.get(id=payload['user_id'])
            
        except jwt.exceptions.DecodeError: 					[3]                                  
            return JsonResponse({'message' : 'INVALID_TOKEN' }, status=401)

        except User.DoesNotExist:                                        
            return JsonResponse({'message' : 'INVALID_USER'}, status=401)
        
        return func(self, request, *args, **kwargs)

    return wrapper
  • [1] : 로그인 데코레이터 안에 중첩 함수 wrapper 선언.
    키워드 인수와 가변 인수는 확장성을 위해 wrapper 함수의 인수로 선언함
  • [2] : JWT를 이용해 검증하는 코드
    1) access_token을 http 헤더 안에 존재하는 'Authorization: ~' 의 ~로 받고 저장한다.
    Authorization 말고 다른 단어를 써도 되지만 일반적으로는 Authorization을 사용한다.
    2) 암호화 할 때 넣었던 user_id를 받아오기 위해 저장했던 access_token과 암호화 할 때 사용되었던 시크릿 키, 알고리즘을 이용해 복호화한다.
    3) User.objects.get 메서드를 이용해 테이블 안에 있는 user_id와 헤더에서 받아온 id를 비교하고 해당되는 유저의 객체를 request.user로 저장한다.

완성한 데코레이터를

#postings/views.py

@login_decorator
def PostingView(View):
		//...

로그인 절차가 필요한 뷰에 걸어주면 끝!

0개의 댓글

관련 채용 정보