如何在Django上的现有登录页面中添加JWT身份验证

cgfeq70w  于 2023-06-25  发布在  Go
关注(0)|答案(1)|浏览(175)

所以我正在学习如何使用Django和DRF,我在Django上创建了一个登录和注册页面。Login and Register user view与他们自己的html页面但是,我不想使用正常的身份验证在Django和想使用Jwt令牌来验证我已经下载了它,并可以使用API/令牌和api/令牌/刷新获得访问和刷新令牌,但我似乎无法找到一种方法来使用它在我已经建立的登录和注册页面进行身份验证

mzillmmw

mzillmmw1#

首先安装Django Rest Framework:

pip install djangorestframework==3.14.0

添加到已安装应用设置中:

config/settings.py

INSTALLED_APPS = [
        # ...
        "rest_framework",
]

为了在我们的项目中实现JWT auth,我们将使用djangorestframework_simplejwt。安装它:

pip install djangorestframework-simplejwt==5.2.2

然后,告诉DRF我们要使用的身份验证后端:
config/settings.py

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": (
        "rest_framework_simplejwt.authentication.JWTAuthentication",
    ),
}

这里有几个简单JWT的设置变量,可以在设置中自定义:

config/settings.py

from datetime import timedelta

SIMPLE_JWT = {
    "ACCESS_TOKEN_LIFETIME": timedelta(minutes=15),
    "REFRESH_TOKEN_LIFETIME": timedelta(days=14),
    "ROTATE_REFRESH_TOKENS": True,
    "BLACKLIST_AFTER_ROTATION": True,
    "UPDATE_LAST_LOGIN": False,
    "ALGORITHM": "HS256",
    "SIGNING_KEY": SECRET_KEY,
    "VERIFYING_KEY": None,
    "AUDIENCE": None,
    "ISSUER": None,
    "JWK_URL": None,
    "LEEWAY": 0,
    "AUTH_HEADER_TYPES": ("Bearer",),
    "AUTH_HEADER_NAME": "HTTP_AUTHORIZATION",
    "USER_ID_FIELD": "id",
    "USER_ID_CLAIM": "user_id",
    "USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule",
    "AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",),
    "TOKEN_TYPE_CLAIM": "token_type",
    "JTI_CLAIM": "jti",
    "SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp",
    "SLIDING_TOKEN_LIFETIME": timedelta(minutes=5),
    "SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1),
}

如果ROTATE_REFRESH_TOKENS设置为True,则将返回一个新的刷新令牌沿着访问令牌。如果BLACKLIST_AFTER_ROTATION设置为True,则提交到刷新视图的刷新令牌将被添加到黑名单中。您需要将'rest_framework_simplejwt.token_blacklist'添加到已安装应用列表中,才能让BLACKLIST_AFTER_ROTATION设置生效。让我们这样做:

config/settings.py

第三方应用

INSTALLED_APPS = [
    # ...
    "rest_framework_simplejwt.token_blacklist",
]

最后,运行以下命令来应用应用的迁移:py manage.py migrate现在,我们需要在用户注册/登录时创建访问和刷新令牌。在下一节中,我们将添加序列化程序和视图来完成此任务。
用户注册和登录端点在用户应用程序中创建一个名为www.example.com的文件serializers.py,并添加以下内容:

users/serializers.py

from django.contrib.auth import authenticate
from rest_framework import serializers

from .models import CustomUser, Profile

class CustomUserSerializer(serializers.ModelSerializer):
    """
    Serializer class to serialize CustomUser model.
    """

    class Meta:
        model = CustomUser
        fields = ("id", "username", "email")

class UserRegisterationSerializer(serializers.ModelSerializer):
    
   # Serializer class to serialize registration requests and create a new user.
    

    class Meta:
        model = CustomUser
        fields = ("id", "username", "email", "password")
        extra_kwargs = {"password": {"write_only": True}}

    def create(self, validated_data):
        return CustomUser.objects.create_user(**validated_data)

class UserLoginSerializer(serializers.Serializer):
    """
    Serializer class to authenticate users with email and password.
    """

    email = serializers.CharField()
    password = serializers.CharField(write_only=True)

    def validate(self, data):
        user = authenticate(**data)
        if user and user.is_active:
            return user
        raise serializers.ValidationError("Incorrect Credentials")

class ProfileSerializer(CustomUserSerializer):
    """
    Serializer class to serialize the user Profile model
    """

    class Meta:
        model = Profile
        fields = ("bio",)

class ProfileAvatarSerializer(serializers.ModelSerializer):
    """
    Serializer class to serialize the avatar
    """

    class Meta:
        model = Profile
        fields = ("avatar",)

请注意,我们还为概要文件创建了一个序列化程序类。然后在views.py

users/views.py

from django.contrib.auth import get_user_model
from rest_framework import status
from rest_framework.generics import GenericAPIView, RetrieveUpdateAPIView
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from rest_framework_simplejwt.tokens import RefreshToken

from . import serializers
from .models import Profile

User = get_user_model()

class UserRegisterationAPIView(GenericAPIView):
    """
    An endpoint for the client to create a new User.
    """

    permission_classes = (AllowAny,)
    serializer_class = serializers.UserRegisterationSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.save()
        token = RefreshToken.for_user(user)
        data = serializer.data
        data["tokens"] = {"refresh": str(token), "access": str(token.access_token)}
        return Response(data, status=status.HTTP_201_CREATED)

class UserLoginAPIView(GenericAPIView):
    """
    An endpoint to authenticate existing users using their email and password.
    """

    permission_classes = (AllowAny,)
    serializer_class = serializers.UserLoginSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data
        serializer = serializers.CustomUserSerializer(user)
        token = RefreshToken.for_user(user)
        data = serializer.data
        data["tokens"] = {"refresh": str(token), "access": str(token.access_token)}
        return Response(data, status=status.HTTP_200_OK)

class UserLogoutAPIView(GenericAPIView):
    """
    An endpoint to logout users.
    """

    permission_classes = (IsAuthenticated,)

    def post(self, request, *args, **kwargs):
        try:
            refresh_token = request.data["refresh"]
            token = RefreshToken(refresh_token)
            token.blacklist()
            return Response(status=status.HTTP_205_RESET_CONTENT)
        except Exception as e:
            return Response(status=status.HTTP_400_BAD_REQUEST)

class UserAPIView(RetrieveUpdateAPIView):
    """
    Get, Update user information
    """

    permission_classes = (IsAuthenticated,)
    serializer_class = serializers.CustomUserSerializer

    def get_object(self):
        return self.request.user

class UserProfileAPIView(RetrieveUpdateAPIView):
    """
    Get, Update user profile
    """

    queryset = Profile.objects.all()
    serializer_class = serializers.ProfileSerializer
    permission_classes = (IsAuthenticated,)

    def get_object(self):
        return self.request.user.profile

class UserAvatarAPIView(RetrieveUpdateAPIView):
    """
    Get, Update user avatar
    """

    queryset = Profile.objects.all()
    serializer_class = serializers.ProfileAvatarSerializer
    permission_classes = (IsAuthenticated,)

    def get_object(self):
        return self.request.user.profile

上述观点不言自明。基本上,用于用户身份验证的视图使用简单JWT的RefreshToken类来生成刷新和访问令牌并将其发送给客户端。此外,注销视图将刷新令牌列入黑名单。其他视图用于获取或更新用户及其简档。现在,让我们在URL中挂钩我们的视图。
转到config/urls.py并添加用户应用程序URL:

config/urls.py

from django.urls import include, path

urlpatterns = [
    # ...
    path("", include("users.urls", namespace="users")),
]

在用户应用程序中,创建一个名为www.example.com的文件urls.py,并按如下所示添加端点:

users/urls.py

from django.urls import path
from rest_framework_simplejwt.views import TokenRefreshView

from users import views

app_name = "users"

urlpatterns = [
    path("register/", views.UserRegisterationAPIView.as_view(), name="create-user"),
    path("login/", views.UserLoginAPIView.as_view(), name="login-user"),
    path("token/refresh/", TokenRefreshView.as_view(), name="token-refresh"),
    path("logout/", views.UserLogoutAPIView.as_view(), name="logout-user"),
    path("", views.UserAPIView.as_view(), name="user-info"),
    path("profile/", views.UserProfileAPIView.as_view(), name="user-profile"),
    path("profile/avatar/", views.UserAvatarAPIView.as_view(), name="user-avatar"),
]

请注意,令牌/刷新端点将用于获取新的访问和刷新令牌。

相关问题