[Django] JWT토큰으로 로그인 구현 (+Thunder Client)

채린·2023년 8월 24일

토큰이 없으면 프엔이랑 연결 시 다른 페이지로 가거나 하는 경우 로그인 상태가 유지되지 않는다고 한다.
로그인 시 받은 토큰을 사용자가 가지고 있으면 '아 이때 로그인했던 @@이구나~'하는 느낌인 것 같다.
(잘 모르지만 토큰은 사용자가 로그인 했을때 발급되는 번호?정도로 생각하면 되는것 같다)
그래서 로그아웃 하면 프엔쪽에서 토큰을 삭제해주기만 하면 된다. (api필요x) 토큰이 삭제되니까 그 토큰을 가지고 있어도 그 사용자를 인정안해줌.. 다시 로그인하면 또 다른 토큰 발급

코드는 대동제 사이트를 가져왔다참고했다..^^..


세팅

settings.py에 추가

from datetime import timedelta

INSTALLED_APPS = [
    # ...
    'rest_framework_simplejwt',
]
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
}
REST_USE_JWT = True
SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(hours=10),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
    'ROTATE_REFRESH_TOKENS': True,
    'AUTH_HEADER_TYPES': ('Bearer',),
    'TOKEN_USER_CLASS': 'account.User',
}

뭔지 잘 모르는데 아무튼 jwt토큰을 쓰는거같다

(참고) https://m.blog.naver.com/home124/223013242697

로그인

serializers.py

class UserLoginSerializer(serializers.Serializer):
    username = serializers.CharField(max_length=64)
    password = serializers.CharField(max_length=128, write_only=True)

    def validate(self, data):
        username = data.get("username", None)
        password = data.get("password", None)

        if User.objects.filter(username=username).exists():
            user = User.objects.get(username=username)
            if not user.check_password(password):
                raise serializers.ValidationError('잘못된 비밀번호입니다.')
            else:
                token = RefreshToken.for_user(user)
                refresh = str(token)
                access = str(token.access_token)

                data = {
                    'id': user.id,
                    'nickname': user.nickname ,
                    'access_token': access
                }
                return data
        else:
            raise serializers.ValidationError('존재하지 않는 사용자입니다.')

        else부분이 포인트!


views.py

class LoginView(views.APIView):
    def post(self, request):
        serializer = UserLoginSerializer(data=request.data)
        if serializer.is_valid():
            return Response({'message': "로그인 성공", 'data': serializer.validated_data}, status=status.HTTP_200_OK)
        return Response({'message': "로그인 실패", 'error': serializer.errors}, status=status.HTTP_400_BAD_REQUEST)

이렇게 해주면 로그인 성공시

이렇게 토큰이 나온다

로그아웃은 백엔드에서 구현 안하고 프엔에서

// 로그아웃 버튼을 클릭했을 때 실행되는 함수
function logout() {
  // 로컬 스토리지에서 토큰 삭제
  localStorage.removeItem('access_token');
  localStorage.removeItem('refresh_token');
  
  // 로그아웃 후 어떤 처리가 필요하다면 여기에 추가
}

이런식으로 토큰을 삭제해주면 된다 (이 코드는 챗지피티가 짜준거라 맞는건진 잘 모름)



로그인 상태가 필요한 기능 구현

기능중에 마이페이지나 좋아요한게시물 목록처럼 현재 로그인한 사용자가 누군지 필요한 경우가 있다.

현재 로그인한 사용자는 request.user이다.

예를들어 마이페이지→자기 프로필 반환하는 코드를 보면


views.py

class MyProfileView(views.APIView):
    permission_classes = [IsAuthenticated]
    def get(self, request, format=None):
        serializer = UserProfileSerializer(request.user)
        return Response({'message': '프로필 가져오기 성공', 'data': serializer.data}, status=status.HTTP_200_OK)

serializer

class UserProfileSerializer(serializers.ModelSerializer): 
     class Meta:
        model=User
        fields=['id','nickname','profile']

request.user가 request를 보낸 사용자 즉 현재 로그인한 사람이다

근데 토큰을 사용하려면 permission_classes = [IsAuthenticated] 가 꼭 필요한거같다

역할은 나도 잘 모르겠다.. 찾아봐야지~~


=> 챗지피티!
permission_classes = [IsAuthenticated]는 Django REST framework에서 인증된 사용자만 허용하도록 제한하는 데 사용되는 클래스입니다. 만약 특정 뷰나 API 엔드포인트에 인증된 사용자만 접근하도록 하려면 해당 뷰의 클래스나 함수에 이 권한 클래스를 적용해야 합니다.
IsAuthenticated 권한 클래스는 JWT 토큰 인증 또는 다른 인증 방식을 통해 로그인한 사용자에게만 접근 권한을 부여합니다. 따라서 로그인 상태가 필요한 기능을 구현할 때 이 권한 클래스를 사용하여 해당 기능을 인증된 사용자에게만 허용할 수 있습니다.

즉, permission_classes = [IsAuthenticated] 를 써줘야 토큰을 활용하여 로그인한 사용자에게만 접근 권한을 부여할 수 있다.



기능 테스트

Thunder Client를 이용해 API가 잘 구현됐는지 확인한다.

Thunder Client 사용법
VScode 확장에서 검색해서 다운로드Http 메소드(GET/POST/등등.. ) 선택하고 우리가 정한 url입력해주고
Body 눌러서 request 써주고 send누르면 된다

로그인 상태로 만들기
로그인 했을때 리턴되는 access token을 복사해서

http 헤더에 Authorization 추가, 옆에 값에 Bearer [토큰] 추가

Send누르면! 토끼씨가 로그인한 토큰을 넣었으니 토끼씨의 프로필이 잘 반환된다

마무리

토큰에 대해 처음 알게 되었다. 백엔드만 공부할 때에는 필요한지 몰랐던 개념이다. 이외에도 어떤 종류의 토큰이 있고, 더 어떻게 활용할 수 있고 활용해야 하는지 공부해 보아야겠다.

0개의 댓글