훈훈훈
파이썬(Django) :: 인증 데코레이터(Decorator) 클래스 본문
# Why 인증 데코레이터
HTTP 프로토콜은 각각의 통신이 독립적이기 때문에 이전에 사용자가 인증을 했는지 알 수 없으며, 새로운 페이지로 넘어 갈떄마다 인증을 해줘야는 문제점이 있다.
이를 해결하기 위해 모든 클래스/함수에 인증 기능을 추가할 수는 있지만 코드가 복잡해지고 길어지기 때문에 인증 기능을 구현 후 데코레이터를 사용하는 것이 좋다,
# 인증 데코레이터 클래스
import jwt
import json
from account.models import Account
from mysite.settings import SECRET_KEY
from django.http import JsonResponse
class LoginConfirm:
def __init__(self, original_function):
self.original_function = original_function
def __call__(self, request, *args, **kwargs):
token = request.headers.get("Authorization", None)
try:
if token:
token_payload = jwt.decode(token, SECRET_KEY, algorithms="HS256")
user = Account.objects.get(name=token_payload['name'])
request.user = user
return self.original_function(self, request, *args, **kwargs)
return JsonResponse({'messaege':'NEED_LOGIN'}, status=401)
except jwt.ExpiredSignatureError:
return JsonResponse({'message':'EXPIRED_TOKEN'}, status=401)
except jwt.DecodeError:
return JsonResponse({'message':'INVALID_USER'}, status=401)
except Account.DoesNotExist:
return JsonResponse({'message':'INVALID_USER'}, status=401)
* _ _call_ _
: 클래스를 함수처럼 호출시킬 수 있는 함수, 데코레이터 함수에서의 wrapper 함수의 역할을 함
* token = request.headers.get("Authorization", None)
: 전송된 HTTP 요청에서 "authorization" 헤더 값을 읽은 후 access token을 얻음
* token_payload = jwt.decode(token, SECRET_KEY, algorithms="HS256")
: JWT를 암호화할때 사용한 SECRET_KEY와 해쉬 알고리즘을 사용하여 token을 복호화 후 token_payload 변수에 할당
* user = Account.objects.get(name=token_payload['name'])
: 복호화한 JWT의 사용자 name을 변수에 할당 후 이후에 비교할 사용자 name과 비교할때 사용
# 인증 기능을 사용한 덧글 클래스
import json
from .models import Comment
from django.views import View
from core.utils import LoginConfirm
from django.http import HttpResponse, JsonResponse
class CommentView(View):
@LoginConfirm
def post(self, request):
data = json.loads(request.body)
Comment.objects.create(name=request.user.name, comment=data['comment']).save()
return HttpResponse(status=200)
def get(self, request):
comment_data = Comment.objects.values()
return JsonResponse({'comments': list(comment_data)}, status=200)
- 위에서 만든 인증 데코레이터를 할당하여 comment를 작성할때 인증을 하도록 작성하였다.
# 결과
wave@Waveui-MacBookPro http -v localhost:8080/comment/input-comment Authorization:"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiMDIxNSJ9.82cpfuCc-_-peNlckW9a1_WVRx-DdXlMVzyHHeVaLGo" comment="input - comment"
POST /comment/input-comment HTTP/1.1
Accept: application/json, */*
Accept-Encoding: gzip, deflate
Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiMDIxNSJ9.82cpfuCc-_-peNlckW9a1_WVRx-DdXlMVzyHHeVaLGo
Connection: keep-alive
Content-Length: 30
Content-Type: application/json
Host: localhost:8080
User-Agent: HTTPie/2.0.0
{
"comment": "input - comment"
}
HTTP/1.1 200 OK
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Mon, 17 Feb 2020 04:27:12 GMT
Server: WSGIServer/0.2 CPython/3.7.4
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
- Authorization에 토큰 값을 전달 후 comment 를 작성하면 200 OK 가 출력되는 것을 확인할 수 있다.
'파이썬 > Django' 카테고리의 다른 글
파이썬(Django) :: migrations 파일 정리 CLI Command (0) | 2020.02.29 |
---|---|
파이썬(Django) :: 장고에 mysql 데이터 베이스 연동하기 (0) | 2020.02.17 |
파이썬(Django) :: 회원 가입 및 로그인 API 구현 (0) | 2020.02.15 |
파이썬(Django) :: SECRET_KEY 분리 방법 (0) | 2020.02.15 |
파이썬(Django) : 인증(Authentication)과 인가(Authorization) (0) | 2020.02.13 |