티스토리 뷰
지난시간 로그인 처리를 훌륭하게 마무리 했다.
이번 시간은 쉬어가는 코너로 JWT 세팅 중 그다지 중요하진 않지만 해놓으면 편한 그런 셋팅을 마무리하려고 한다.
일단 필요한 기능이 "JWT_GET_USER_SECRET_KEY" 이거다. 서명할 때 사용자 개인 키를 적용해 서명을 암호화할 때 사용하게 한다. 이 기능이 있어야 나중에 로그아웃도 만들 수 있다.
account 앱에 utils.py 파일을 하나 만들자.
이렇게 만들고 utils.py 에 아래와 같이 코딩하자.
account/utils.py
def get_secret_key(model):
return model.secret
그냥 이렇게만 코딩해도 괜찮다. 이렇게 코딩하고 settings.py 파일을 열자.
funny_picture/settings.py
#
# 생략
#
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(hours=168),
'JWT_ALLOW_REFRESH': True,
'JWT_GET_USER_SECRET_KEY': 'account.utils.get_secret_key',
'JWT_VERIFY': True,
'JWT_AUTH_HEADER_PREFIX': 'FNY'
}
#
# 생략
#
이렇게 하면 DB에 지정되어있는 account_user 테이블에 저장되어 있는 secret 값이 서명에 사용되게 된다. 그래서 이 값은 외부에 노출 되면 안되므로 나중에 Serialize에서 secret 값을 지워주도록 하자.
account/serializers.py
#
# 생략
#
class UserSerializer(serializers.ModelSerializer):
auths = AuthSerializer(many=True, read_only=True)
class Meta:
model = User
fields = [
'id'
, 'email'
, 'status'
, 'is_active'
, 'last_login'
, 'auths'
, 'created_at'
, 'updated_at'
]
#
# 생략
#
이렇게 secret 값을 지워준다.
이렇게 수정 한 뒤에 서버를 재기동하고 다시 로그인해보도록 하자.
이렇게 보면 토큰에 무슨 변화가 생긴것 같아 보이진 않을거다. 그런데 이 토큰을 https://jwt.io/ 에 가져가서 확인해보면 이전과 다른 결과를 볼 수 있다.
이렇게 서명의 유효성이 달라지게 된다.
로그아웃 구현하기
사용자가 이제 "로그아웃"을 했다고 치자. 그러면 이전에 사용하던 토큰은 사용할 수 없어야한다.
그렇다면 어떻게 해야할까?
간단하게 사용자의 Secret Key를 변경하면 서명이 유효하지 않게 되니 더이상 토큰을 사용할 수 없게 되어버린다.
그래서 사용자 로그아웃 API를 추가해 만들어주자.
account/view.py
import uuid
from django.shortcuts import render
from django.contrib import auth
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from .serializers import UserSerializer
from .models import User
class HelloView(APIView):
name = 'hello-view'
def get(self, request, *args, **kwargs):
return Response({'hello': 'world!'})
class UserInfo(APIView):
name = 'user-info'
permission_classes = [IsAuthenticated]
def get(self, request, *args, **kwargs):
user_id = request.query_params.get("id")
query = User.objects.get(id=user_id)
serializer = UserSerializer(query, many=False)
return Response( serializer.data )
#사용자 로그아웃
@api_view(['POST'])
def user_logout(request):
if request.user:
user = request.user
User.objects.filter(email=user).update(secret=uuid.uuid4())
auth.logout(request)
return Response(status=status.HTTP_200_OK)
상단에 uuid와 api_view를 import한 코드 놓치면 안되고 제일 하단에 user_logout 메서드가 추가된 부분을 잘 파악하면 된다. 사용자 정보가 있는 상태로 로그아웃 API를 호출하면 사용자 정보에서 secret 값을 새로운 uuid 값을 넣어서 수정하는 코드다. 그 뒤에 세션에 남아있는 사용자 정보도 auth.logout 메서드를 통해 지워버린다.
account/urls.py
from django.conf.urls import url
from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token, verify_jwt_token
from .views import *
urlpatterns = [
url(r'^v1/hello', HelloView.as_view(), name=HelloView.name)
, url(r'^v1/get-user', UserInfo.as_view(), name=UserInfo.name)
, url(r'^v1/get-auth-token', obtain_jwt_token) # 사용자 로그인(토큰발급)
, url(r'^v1/token-verify', verify_jwt_token) # 사용자 토큰 유효성 검사
, url(r'^v1/token-refresh', refresh_jwt_token) # 사용자 토큰 갱신
, url(r'^v1/logout', user_logout) # 사용자 로그아웃
]
제일 아래 사용자 로그아웃 메서드 호출하는 URL을 추가해줬다. 이제 테스트 해보도록 하자.
로그아웃 하기전 secret 값은 위와 같다.
그리고 로그아웃을 호출해보도록 하자.
정상적으로 200 OK 값을 응답 받았다. 그럼 이제 DB 를 확인해 secret 값이 변경 되었는지 확인해보자.
값이 정상적으로 바뀐 것을 확인할 수 있다.
아, 그리고 model.py 에 코드를 추가해줘야한다.
account/models.py
# 사용자 계정 테이블 모델
class User(AbstractBaseUser):
id = models.BigAutoField(primary_key=True)
email = models.EmailField(max_length=254, unique=True) # 이메일 주소
secret = models.UUIDField(default=uuid.uuid4) # 사용자 서명용 비밀키
status = models.CharField(max_length=10, default=USER_STATUS.get('ACTIVE', 'ACTIVE')) # 사용자 현재 상태
is_active = models.BooleanField(default=False) # 계정 활성화 여부
created_at = models.DateTimeField(auto_now_add=True) # 계정 생성일
updated_at = models.DateTimeField(auto_now=True) # 계정 수정일
objects = UserManager() # 사용자 정보를 관리하는 클래스는 지정한다.
USERNAME_FIELD = 'email' # 사용자 이름으로 사용될 필드의 이름을 지정한다.
def __str__(self):
return self.email
# 사용자 PK 값을 가져오기위한 함수
def get_id(self):
return self.id
중간에 "def __str__(self)" 이 코드 꼭 추가해준다음에 로그아웃을 테스트 해보도록 하자. 잘 안되면 로그인부터 다시 테스트 해보면 잘 될거다.
내가 저 str 코드 빼먹어서 중간에 곤란곤란했었다.
암튼 이렇게 까지 하면 일단 대충 로그인, 로그아웃, 서명키 설정까지 마무리 되었다.
이제 관리자 페이지 로그인을 만들어보도록 하자.
그럼 오늘은 이만 안녕!
'Dev > 프로그래밍 잘하기' 카테고리의 다른 글
[짤방 검색기] #13. 로그인 하기(JWT로 토큰 받기) (0) | 2019.07.03 |
---|---|
[짤방 검색기] #12. 사용자 정보 Serializing 하기 (0) | 2019.06.17 |
[짤방 검색기] #11. Django 사용자 정보 만들기(下) (2) | 2019.06.13 |
[짤방 검색기] #10. Django 사용자 정보 만들기(上) (0) | 2019.06.11 |
[짤방 검색기]#9. 본격 개발 준비 중 - 클래스란 무엇인가요? (0) | 2019.06.11 |