Django-JWT
- 공유 링크 만들기
- X
- 이메일
- 기타 앱
Django-JWT
JWT을 이용한 로그인을 구현해보았다.
우선 jwtTest라는 프로젝트를 만들고 user라는 app을 생성하였다.
Django 프로젝트 생성
Django App 생성
Django REST framework JWT 설치
pip install djangorestframework djangorestframework-jwt
REST framework 와 JWT를 설치해준다.
settings.py 환경 셋팅
settings.py INSTALLED_APP에 restframework를 추가해준다.
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'rest_framework_jwt', 'user', ]
settings.py에 다음과 같이 추가해준다.
REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.AllowAny', ), 'DEFAULT_AUTHENTICATION_CLASSES':( 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication', ), } JWT_AUTH = { 'JWT_ENCODE_HANDLER': 'rest_framework_jwt.utils.jwt_encode_handler', 'JWT_DECODE_HANDLER': 'rest_framework_jwt.utils.jwt_decode_handler', 'JWT_PAYLOAD_HANDLER': 'rest_framework_jwt.utils.jwt_payload_handler', 'JWT_PAYLOAD_GET_USER_ID_HANDLER': 'rest_framework_jwt.utils.jwt_get_user_id_from_payload_handler', 'JWT_RESPONSE_PAYLOAD_HANDLER': 'rest_framework_jwt.utils.jwt_response_payload_handler', 'JWT_SECRET_KEY': SECRET_KEY, 'JWT_GET_USER_SECRET_KEY': None, 'JWT_PUBLIC_KEY': None, 'JWT_PRIVATE_KEY': None, 'JWT_ALGORITHM': 'HS256', 'JWT_VERIFY': True, 'JWT_VERIFY_EXPIRATION': True, 'JWT_LEEWAY': 0, 'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=3000), 'JWT_AUDIENCE': None, 'JWT_ISSUER': None, 'JWT_ALLOW_REFRESH': True, 'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7), 'JWT_AUTH_HEADER_PREFIX': 'JWT', 'JWT_AUTH_COOKIE': None, }
serializers.py 생성
User model을 이용한 serializer를 만들어 준다.
from rest_framework import serializers from django.contrib.auth import get_user_model # refer to model class using get_user_model_helper() User = get_user_model() class UserSerializer(serializers.ModelSerializer): new_password = serializers.CharField(required=False, write_only=True) def create(self, validated_data): user = User.objects.create( username=validated_data['username'], email=validated_data['email'] ) user.set_password(validated_data['password']) user.save() return user def update(self, instance, validated_data): instance.email = validated_data['email'] if validated_data.get('new_password') != None: instance.set_password(validated_data['new_password']) instance.save() return instance def destroy(self, instance): instance.delete() class Meta: model = User extra_kwargs = { 'password': {'write_only': True}, 'new_password' : {'write_only': True}, 'email':{'required':False}, } fields = ('id', 'username', 'email', 'password', 'new_password')
views.py
permission을 추가해준다.
나는 로그인이 되어있지 않은 상태에서는 user를 생성하는 것만 되게끔 하였다.
그리고 update와 destroy는 user 자신이거나 admin의 경우 가능하도록 권한을 부여하였다.
from django.shortcuts import render from rest_framework import viewsets from .serializers import UserSerializer from django.contrib.auth import get_user_model from rest_framework_jwt.authentication import JSONWebTokenAuthentication from rest_framework.decorators import permission_classes, authentication_classes from rest_framework.permissions import IsAuthenticated, AllowAny from rest_framework.generics import RetrieveAPIView from rest_framework.response import Response from rest_framework import status from .permissions import IsLoggedInUserOrAdmin, IsAdminUser User = get_user_model() @authentication_classes((JSONWebTokenAuthentication,)) class UserViewSet(viewsets.ModelViewSet): queryset = User.objects.all() serializer_class = UserSerializer lookup_field = 'username' def get_permissions(self): if self.action == 'create' : return (AllowAny(),) elif self.action == 'update' or self.action == 'destroy': return (IsLoggedInUserOrAdmin(),) elif self.action == 'list': return (IsAdminUser(),) return (IsLoggedInUserOrAdmin(),) @permission_classes((IsAuthenticated,)) class UserRetrieveAPIView(RetrieveAPIView): serializer_class = UserSerializer def get(self, request, *args, **kwargs): serializer = self.serializer_class(request.user) return Response(serializer.data, status=status.HTTP_200_OK)
UserRetrieveAPIView는 token을 가진 user 정보를 가져오기 위해 사용하였다.
추가로 커스터마이징한 permission은 아래와 같다.
from rest_framework import permissions class IsLoggedInUserOrAdmin(permissions.BasePermission): def has_object_permission(self, request, view, obj): return obj == request.user or request.user.is_staff class IsAdminUser(permissions.BasePermission): def has_permission(self, request, view): return request.user and request.user.is_staff def has_object_permission(self, request, view, obj): return request.user and request.user.is_staff
urls.py 추가
from django.contrib import admin from django.urls import path, include from rest_framework import routers from user import views from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token router = routers.DefaultRouter() router.register(r'users', views.UserViewSet) urlpatterns = [ path('admin/', admin.site.urls), path('api/', include(router.urls)), path('api/auth/login/', obtain_jwt_token), path('api/auth/me/', views.UserRetrieveAPIView.as_view()), path('api/auth/refresh/', refresh_jwt_token), ]
[ 참고 사이트 ]
Django REST Framework
end point 참고
from http://sssunda.tistory.com/214 by ccl(A) rewrite - 2020-03-06 11:54:24
- 공유 링크 만들기
- X
- 이메일
- 기타 앱
댓글
댓글 쓰기