DRF JWT 用户认证
作者:互联网
环境说明:
python: 3.8
django: 3.2
djangorestframework-jwt 1.11.0
项目大概说明:
基于Django中的系统用户表进行扩展,通过jwt进行用户权限认证。
目录结构:
认证相关 视图
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.viewsets import ViewSet
from .serializers import UserInfoModelSerializer
class LoginViewSet(ViewSet):
# 设置这个视图不需要认证就可以访问
authentication_classes = []
# 设置这个视图不需要任何权限就可以访问
permission_classes = []
@action(methods=["POST"], detail=False)
def get_token(self, requests):
# 验证传递过来的用户名密码是否为空
if requests.data.get("username") and requests.data.get("password"):
# 通过序列化器进行序列化,对密码进行验证
serializer = UserInfoModelSerializer(data=requests.data)
# 判断序列化器验证是否成功
serializer.is_valid()
return Response(status=status.HTTP_200_OK, data=serializer.data)
else:
return Response({'code': 'errors'})
认证相关 序列化类
from rest_framework import serializers
from rest_framework_jwt.serializers import jwt_payload_handler
from rest_framework_jwt.utils import jwt_encode_handler
from system.models import Users
# 用户获取token的序列化器
class UserInfoModelSerializer(serializers.ModelSerializer):
username = serializers.CharField()
# write_only=True 反序列化的时候必须写入,但是序列化的时候不会显示
password = serializers.CharField(write_only=True)
# read_only=True 反序列化的时候不需要这个字段,但是返回的时候会显示
token = serializers.CharField(read_only=True)
class Meta:
model = Users
fields = ["id", "username", "password", "token"]
def validate(self, attrs):
# 对密码进行校验
try:
user = Users.objects.get(username=attrs.get("username"))
except Users.DoesNotExist:
raise serializers.ValidationError(detail="用户名密码错误", code="validate")
# 通过系统默认表中的check_password来检查用户输入的明文密码和数据库中的密码是否是相同的
if user.check_password(attrs.get("password")):
payload = jwt_payload_handler(user)
# 要将token字段返回给前端就必须要在fields里面加上token字段
# 通过jwt_encode_handler生成token
attrs["token"] = jwt_encode_handler(payload)
return attrs
else:
raise serializers.ValidationError(detail="用户名密码错误", code="validate")
认证相关 视图
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.viewsets import ViewSet
from .serializers import UserInfoModelSerializer
class LoginViewSet(ViewSet):
authentication_classes = []
permission_classes = []
@action(methods=["POST"], detail=False)
def get_token(self, requests):
# 验证传递过来的用户名密码是否为空
if requests.data.get("username") and requests.data.get("password"):
# 通过序列化器进行序列化
serializer = UserInfoModelSerializer(data=requests.data)
# 判断序列化器验证是否成功
serializer.is_valid()
return Response(status=status.HTTP_200_OK, data=serializer.data)
else:
return Response({'code': 'errors'})
认证相关 总路由
from django.urls import path, include
from apps import views
from apps.views import BookViewSet
from myauth.views import LoginViewSet
urlpatterns = [
path('login/', LoginViewSet.as_view({"post": 'get_token'})),
# path('book/', BookViewSet.as_view({'get': 'list', 'post': 'create'}))
path('system/', include('system.urls')),
]
urlpatterns += router.urls
系统用户表 Model
扩展了系统用户表之后,需要在settings中更改认证用户模型的配置
book/settings.py
# Users为自定定义的系统用户模型名称
AUTH_USER_MODEL = 'system.Users'
from django.contrib.auth.models import AbstractUser
from django.db import models
STATUS_CHOICES = (
(0, "禁用"),
(1, "启用"),
)
# 继承AbstractUser,相当于在系统用户表的基础上进行扩展字段
class Users(AbstractUser):
username = models.CharField(max_length=150, unique=True, db_index=True, verbose_name="用户账号", help_text="用户账号")
email = models.EmailField(max_length=255, verbose_name="邮箱", null=True, blank=True, help_text="邮箱")
mobile = models.CharField(max_length=255, verbose_name="电话", null=True, blank=True, help_text="电话")
avatar = models.CharField(max_length=255, verbose_name="头像", null=True, blank=True, help_text="头像")
name = models.CharField(max_length=40, verbose_name="姓名", help_text="姓名")
GENDER_CHOICES = (
(0, "未知"),
(1, "男"),
(2, "女"),
)
gender = models.IntegerField(
choices=GENDER_CHOICES, default=0, verbose_name="性别", null=True, blank=True, help_text="性别"
)
USER_TYPE = (
(0, "后台用户"),
(1, "前台用户"),
)
user_type = models.IntegerField(
choices=USER_TYPE, default=0, verbose_name="用户类型", null=True, blank=True, help_text="用户类型"
)
update_datetime = models.DateTimeField(auto_now=True, null=True, blank=True, help_text="修改时间", verbose_name="修改时间")
create_datetime = models.DateTimeField(auto_now_add=True, null=True, blank=True, help_text="创建时间",
verbose_name="创建时间")
class Meta:
db_table = "system_users"
verbose_name = "用户表"
verbose_name_plural = verbose_name
ordering = ("-create_datetime",)
系统用户表 序列化器
from django.contrib.auth.hashers import make_password
from rest_framework import serializers
from .models import Users
# 用于获取用户信息的序列化器,不返回密码
class UserInfoSerializer(serializers.ModelSerializer):
# 针对模型中含有选项的,通过`get_字段名称_display`可以返回具体的名称
gender = serializers.CharField(source="get_gender_display", read_only=True)
class Meta:
model = Users
fields = ('id', 'username', 'email', 'mobile', 'avatar', 'name', 'gender', 'user_type',)
# 用于创建用户使用的序列化器
class UserCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Users
fields = ('id', 'username', 'password', 'name', 'email', 'mobile', 'gender', 'user_type',)
# 增加约束键,对需要部分进行约束,相当于添加了判断
extra_kwargs = {
'username': {
'max_length': 20,
'min_length': 5
},
'password': {
'max_length': 20,
'min_length': 8,
'write_only': True
},
}
# 对单个字段进行验证,使用django自带的方法make_password
def validate_password(self, value):
password = self.initial_data.get("password")
if password:
return make_password(value)
return value
系统用户表 视图
from rest_framework.decorators import action
from rest_framework.viewsets import ModelViewSet
from .models import Users
from .serializers import UserInfoSerializer, UserCreateSerializer
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated
from myauth.authentications import JWTAuthentication
class UserModelViewSet(ModelViewSet):
queryset = Users.objects.all()
# 使用我们自定义的验证方法
authentication_classes = [JWTAuthentication]
# 登录成功才能进行访问
permission_classes = [IsAuthenticated]
# 重写类方法,判断从视图请求过来的方法来选择序列化器,GET请求对应list_user,POST对应create_user
def get_serializer_class(self):
if self.action == "list_user":
return UserInfoSerializer
elif self.action == "create_user":
return UserCreateSerializer
@action(methods=['get'], detail=True)
def list_user(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
@action(methods=['post'], detail=True)
def create_user(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
系统用户表 路由
from django.urls import path, re_path
from rest_framework.routers import DefaultRouter, SimpleRouter
from .views import UserModelViewSet
urlpatterns = [
# 通过不同的请求方式请求到不同的方法中去
path('user/', UserModelViewSet.as_view({'get': 'list_user', 'post': 'create_user'})),
re_path('user/(?P<pk>\d+)/$', UserModelViewSet.as_view({'get': 'list_user'})),
]
标签:get,JWT,rest,认证,framework,user,import,True,DRF 来源: https://www.cnblogs.com/shangcc205/p/16455511.html