介绍
创建系统管理app,用于管理系统的用户,角色,权限,登录等功能,项目中将使用django-rest_framework进行用户认证和权限解析。这里将完成用户认证
用户验证
rest_framework.authentication模块中的认证类,例如:
session认证:SessionAuthentication(基于session)
token 认证:TokenAuthentication(API Token)
自定义认证:BasicAuthentication(HTTP Basic Auth)
- 这里采用djangorestframework-simplejwt设计自定义认证类和自定义登录
pip install djangorestframework-simplejwt
- 创建用户模型表user
from django.db import models from django.contrib.auth.hashers import make_password, check_password
# Create your models here.
class User(models.Model):
username = models.CharField(max_length=255, unique=True, verbose_name="手机号")
password = models.CharField(max_length=255, unique=False, verbose_name="密码")
is_vip = models.BooleanField(default=False,verbose_name="是否为vip")
vip_expires_at = models.DateTimeField(auto_now_add=True,verbose_name="vip过期时间")
is_active = models.BooleanField(default=True)
class Meta:
db_table = "user"
verbose_name = "用户账号表"
verbose_name_plural = verbose_name
- 数据库迁移
python manage.py makemigrations
python manage.py migrate
- 在根目录下创建utils目录,在utils目录中创建文件Authentication.py和jwt.py
## Authentication.py
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework import serializers
from user.models import User
# 自定义认证类
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
"""
自定义登录认证,使用自有用户表
username、password这两个字段为必传字段因为 DRF 要检查这些字段是否有效
username_field = 'phone_number' 这是重命名了,username必传字段设置为了phone_number字段必传
phone_number = serializers.CharField(required=False) # 这个是设置了自定义的字段是否必传
"""
def validate(self, attrs):
username = attrs.get("username")
password = attrs.get("password")
if not username or not password:
raise serializers.ValidationError("phone_number and password are required")
try:
user = User.objects.get(username=username, password=password)
except User.DoesNotExist:
raise serializers.ValidationError("No user found with this username and password.")
print(user)
refresh = self.get_token(user)
data = {"userId": user.id, "token": str(refresh.access_token), "refresh": str(refresh),
'is_vip': user.is_vip}
return data
class MyTokenObtainPairView(TokenObtainPairView):
serializer_class = MyTokenObtainPairSerializer
## jwt.py
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework_simplejwt.exceptions import InvalidToken, AuthenticationFailed
from django.utils.translation import gettext_lazy as _
# 自定义的用户模型
from user.models import User
class MyJWTAuthentication(JWTAuthentication):
'''
修改JWT认证类,返回自定义User表对象
'''
def get_user(self, validated_token):
try:
user_id = validated_token['user_id']
except KeyError:
raise InvalidToken(_('Token contained no recognizable user identification'))
try:
user = User.objects.get(**{'id': user_id})
except User.DoesNotExist:
raise AuthenticationFailed(_('User not found'), code='user_not_found')
return user
- 在settings.py同级目录下创建drf_settings.py 并引入settings.py 中
## drf_settings.py
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'utils.jwt.MyJWTAuthentication' # 认证方式为自定义的认证类
],
}
引入settings中
import drf_settings
REST_FRAMEWORK = drf_settings.REST_FRAMEWORK
- 创建一个app:userauth,在views.py中写入一个接口视图
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
# Create your views here.
class UserTestView(APIView):
def post(self, request,*args, **kwargs):
s = str(request.user.__dict__)
return Response(s)
- 在app:userauth:urls中设置路由
from django.urls import path, include
from rest_framework import routers
from rest_framework_simplejwt.views import TokenVerifyView, TokenRefreshView
from utils.authentication import MyTokenObtainPairView
from userauth.views import UserTestView
router = routers.DefaultRouter()
urlpatterns = [
path("login/", MyTokenObtainPairView.as_view()), # 登录
path("refresh/", TokenRefreshView.as_view(), name="token_refresh"), # 刷新token
path("verify/", TokenVerifyView.as_view(), name="token_verify"), # 验证token
path("test/", UserTestView.as_view(), name="test")
]
urlpatterns.append(path('', include(router.urls)))
-
这里没有写注册功能,所以只有手动在数据库中创建一个用户
-
使用postman进行登录测试
-
刷新token测试
-
接口测试
参考链接:https://blog.csdn.net/qq_42410176/article/details/130568130?spm=1001.2014.3001.5502