본문 바로가기

Django

django JWT 사용 방법

JWT란?

JsonWebToken으로 말 그대로 JSON 객체로 정보를 전달하는 방식이다.

설치

$ pip install pyjwt

JWT 인증 구현하기

header의 META 데이터를 통해 정보 얻을 수 있게 로직 구성

# 본인이 원하는 폴더에서 작업하기
import jwt
from django.conf import settings
from rest_framework import authentication, exceptions
from users.models import User

class JWTAuthentication(authentication.BaseAuthentication):
      def authenticate(self, request):
          try:
              token = request.META.get('HTTP_AUTHORICATION')
            if token is None:
                  return None
            # header에서 받은 token 내용에 선행값 (ex. Bearer)이 있다면 token값이랑 분리 시켜준다.
            jwt, jwt_token = token.split(' ')
            # SECRET_KEY는 django의 SECRET_KEY를 사용함
            decoded = jwt.decode(jwt_token, settings.SECRET_KEY, algorithms=['HS256'])
            pk = decoded.get('pk')
            return user, None
        except jwt.exceptions.DecodeError:
              raise exceptions.AuthenticationFailed(default='JWT Format Invalid')

기본 인증 체계는 DEFATULT_AUTHENTICATION 설정을 사용(아래 코드 참고)하여 전역적으로 설정할 수 있다.

코드는 settings.py에서 등록할 수 있다.

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'config.authentication.JWTAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}

REST_FRAMEWORK에 등록한 의미를 알아보면 (config.authetication.JWTAuthentication)<app이름.파일이름.클래스or함수 이름>으로 구성되어있다. (처음 로직 작성 한 부분의 경로이다.)

위와 같이 구성이 다되었다면 다음과 같이 view 로직을 구성할 수 있다.

from django.contrib.auth import authenticate


def login(request):
    try:
          # request에서 입력받은 email과 password를 가져온다.
        email = request.data.get('email', None)
        password = request.data.get('password', None)

        # 내가 로그인한 user가 진짜 맞는지 확인하는 작업이 필요함
        # authenticate는 username(지정한 대로 변경가능)과 password가 필요하다.
        # authenticate 메서드를 사용해서 User를 찾아야한다.
        user = authenticate(email=email, password=password)

        # 사용자를 찾았을때 (user가 None이 아닐때)
        if user is not None:
              # JWT값안에 단순히 pk값만 넣어준다.
            # 그렇다면 JWT값을 encoded해서 token안에 담은 pk값에 대한 내용을 볼 수 있는것이다.
              encoded_jwt = jwt.encoded(
                    {
                      'pk': user.pk
                },
                  settings.SECRET_KEY,
                  algorithm='HS256'
            )
            return Response(data={'token': encoded_jwt}, status=status.HTTP_201_CREATED)
          else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)
        except Exception as e:
          return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)

token 값을 담을때 중요한 정보를 담아선 안된다. 단순히 user를 구별할 수 있는 식별자 수준의 정보만 담는게 좋다.

그렇다면 그런 정보만 담을거면 왜 token을 사용하는지에 대해 의문을 품을 수도 있다.

서버에서는 token에 어떠한 변경사항이 하나라도 있었는지를 판단한다.

현재 token 데이터를 누군가 건드렸느냐 아니면 그대로이냐가 제일 중요하다.

token 내부의 정보에 대해서는 그렇게 중요하지 않다. 이정도로 알고 있으면 될듯하다.

여기까지 작성이 되었으면 각자의 방법을 통해서 token값이 제대로 호출 되는지 확인 할 수 있다.

request Body값에 email(username)과 password를 꼭 넣어주길 바란다.

그리고 받은 token값에 대해서 확인하는 것 까지 해보자

물론 다른 로직을 구성해서 테스트 해야한다. header에 KEY : Authorization / VALUE : token 값 을 넣고 테스트 해보면 된다.

참고

Django에 인증 방법이 두가지가 있는데 JWT 말고 TokenAuthentication이라는게 있는데

JWT과의 차이점은 JWT은 DB에 저장되지 않는다는 점이다.

DRF에서 제공하는 TokenAuthentication의 경우엔 token의 일부를 DB에 저장해야한다.

그리고 해당 토큰을 받아서 암호화 같은 작업들을 해줘야한다.