🍏
Django Rest FrameworkでJWTを使ってみる。
初めに
今回はDRFでJWT認証を使用してみようと思う。
環境
- python version 3.9.17
- Django version 4.2.3
- Django Rest Framework version 3.14.0
- Simple JWT ←JWT認証のパッケージ
ディレクトリ構造
ディレクト構造
drfTest/
├── accounts/
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ ├── views.py
├── drfTest/
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ ├── wsgi.py
├── db.sqlite3
├── manage.py
accounts/models.py
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.db import models
class CustomUserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
if not email:
raise ValueError("The Email field must be set")
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self.create_user(email, password, **extra_fields)
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
date_joined = models.DateTimeField(auto_now_add=True)
password = models.CharField(max_length=128)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['password']
def __str__(self):
return self.email
SerializerとViewSetの設定
accounts/serializers.py
from rest_framework import serializers
from .models import CustomUser
class CustomUserSerializer(serializers.ModelSerializer):
class Meta:
model = CustomUser
fields = ['id', 'email', 'password']
extra_kwargs = {'password': {'write_only': True}}
#createメソッドをオーバーライドしている。
def create(self, validated_data):
user = CustomUser(
email=validated_data['email'],
username=validated_data['username']
)
user.set_password(validated_data['password'])
user.save()
return user
accounts/views.py
from rest_framework import viewsets, permissions, status
from rest_framework.response import Response
from .models import CustomUser
from .serializers import CustomUserSerializer
#permission_classesのオプションを新たに作成している。
#IsUserOrReadOnlyは、ユーザーが自分の情報を見ることはできるが、他のユーザーの情報を見ることはできないようにする。
class IsUserOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
return obj == request.user
class CustomUserViewSet(viewsets.ModelViewSet):
def get_queryset(self):
return CustomUser.objects.filter(id=self.request.user.id)
queryset = CustomUser.objects.all()
serializer_class = CustomUserSerializer
permission_classes = [permissions.IsAuthenticated, IsUserOrReadOnly]
urls.pyの設定
drfTest/urls.py
from django.urls import include, path
from rest_framework import routers
from django.conf import settings
from accounts import views as accounts_views
router = routers.DefaultRouter()
router.register(r'users', accounts_views.CustomUserViewSet)
urlpatterns = [
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
#JWTのためのURL
path('api/token/', jwt_views.TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', jwt_views.TokenRefreshView.as_view(), name='token_refresh'),
]
テストしてみる
ターミナルでrunserverする。
terminal
python manage.py runserver 8080
下記のコマンドを入力してトークンを取得してみる
terminal
curl -X POST -H "Content-Type: application/json" -d '{"email": "example@mmail.com", "password"
: "example"}' http://localhost:8080/api/token/
example@mail.comとexampleは自身で作成したユーザのemailアドレスとパスワードにする。
結果
terminal
{"refresh":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTY5NjQzMzk5MiwiaWF0IjoxNjkzODQxOTkyLCJqdGkiOiJkMTlmMDI2NDliMWQ0NTY2OWY3NDQ0MGQxNzBkODkyYyIsInVzZXJfaWQiOjF9.aXeTuu5E7mhOAXxBHL7nEp2_Tefz4YKej2Bf8l7rrrU","access":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjkzODQyODkyLCJpYXQiOjE2OTM4NDE5OTIsImp0aSI6IjY3NWNlYjg2YzNiMjQ3NDdiYWRkYzk1YzAxMTcyMzRmIiwidXNlcl9pZCI6MX0.s8IT39j8L0Ja7XCJm3HVe_re8FYkZixXY7PPUeE2lHA"}
アクセストークンとリフレッシュトークンが返ってきた。
Discussion