본문 바로가기

Django/Authentication

[Django] DRF의 simple-jwt를 이용한 로그인 기능 구현 (1)

 

요즘은 DRF의 jwt 인증 부분 라이브러리를 simple-jwt를 사용한다고 한다. pyjwt 등 이전에 사용하던 jwt 인증 라이브러리는 더 이상의 업데이트가 이루어지지 않고 최근 활발히 업데이트가 되는 simple-jwt 라이브러리를 이용한 로그인 기능을 구현할 것이다.

 

1. simple-jwt 라이브러리 설치 및 세팅

https://smin1620.tistory.com/40

 

[Django] DRF의 simpleJWT

https://django-rest-framework-simplejwt.readthedocs.io/en/latest/getting_started.html#usage Getting started — Simple JWT 5.1.0.post11+g58b1874 documentation © Copyright 2020, David Sanders Revisi..

smin1620.tistory.com

 

이 글에서 simple-jwt 설치 및 장고 설정 세팅하는 법을 똑같이 적용을 하면 된다.

 

여기서 우리는 simple-jwt 라이브러리에서 내장 Serializer를 사용할 것이다.

" TokenObtainPairSerializer "
먼저 TokenObtainPairSerializer의 로직을 보면
# TokenObtainPairSerializer

class TokenObtainPairSerializer(TokenObtainSerializer):
    @classmethod
    def get_token(cls, user):
        return RefreshToken.for_user(user)

    def validate(self, attrs):
        data = super().validate(attrs)

        refresh = self.get_token(self.user)

        data['refresh'] = str(refresh)
        data['access'] = str(refresh.access_token)

        if api_settings.UPDATE_LAST_LOGIN:
            update_last_login(None, self.user)

        return data​


def get_token(cls, user) 내장 함수에서 user에 맞는 refresh token을 생성하여 리턴한다.
def validate(self, attrs) 내장 함수로 refresh token을 확인하고, user의 refresh token, access token을 리턴해준다.

 

 

 

2. 로그인 기능 구현

# 로그인 - 일반 사용자용

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from django.contrib.auth.hashers import check_password
from rest_framework.views import APIView


class UserLoginAPI(APIView):
    def post(self, request):
        username = request.data['username']
        password = request.data['password']

        user = User.objects.filter(username=username).first()

        # 만약 username에 맞는 user가 존재하지 않는다면,
        if user is None:
            return Response(
                {"message": "존재하지 않는 아이디입니다."}, status=status.HTTP_400_BAD_REQUEST
            )

        # 비밀번호가 틀린 경우,
        if not check_password(password, user.password):
            return Response(
                {"message": "비밀번호가 틀렸습니다."}, status=status.HTTP_400_BAD_REQUEST
            )

        # user가 맞다면,
        if user is not None:
            token = TokenObtainPairSerializer.get_token(user) # refresh 토큰 생성
            refresh_token = str(token) # refresh 토큰 문자열화
            access_token = str(token.access_token) # access 토큰 문자열화
            response = Response(
                {
                    "user": UserSerializer(user).data,
                    "message": "login success",
                    "jwt_token": {
                        "access_token": access_token,
                        "refresh_token": refresh_token
                    },
                },
                status=status.HTTP_200_OK
            )

            response.set_cookie("access_token", access_token, httponly=True)
            response.set_cookie("refresh_token", refresh_token, httponly=True)
            return response
        else:
            return Response(
                {"message": "로그인에 실패하였습니다."}, status=status.HTTP_400_BAD_REQUEST
            )

 

UserLoginAPI(APIView) : Django의 APIView 클래스를 이용한다.

def post(self, request) : 로그인 요청을 post 메서드로 요청해야하기 때문에 post 함수를 사용한다.

token = TokenObtainPairSerializer.get_token(user)
refresh_token = str(token)
access_token = str(token.access_token) 
: user의 토큰을 refresh, access 토큰을 생성한다.

response.set_cookie : post 메서드로 로그인 하였을 때, 생성된 토큰을 쿠키에 담아 전송하는 코드이다.

 

 

3. 출력