django rest framework 之restframework_jwt和注册登录的实现(十一)

JWT的组成:三部分组成 header部分:JWT的类型和加密算法
payload部分:JWT的签发者、JWT的接收者、JWT的持续时间,以及一些用户非敏感信息
signatrue部分:签名部分是由Header和Payload组合而成,将Header和Claim这两个Json分别使用Base64方式进行编码,生成字符串Header和Payload,然后将Header和Payload以Header.Payload的格式组合在一起形成一个字符串,然后使用上面定义好的加密算法和一个密匙(这个密匙存放在服务器上,用于进行验证)对这个字符串进行加密,形成一个新的字符串,这个字符串就是Signature

一.场景一:登录接口的实现

  1. 安装restframework_jwt
    pip install restframework_jwt
  2. 创建一个users的app
    python manager startapp users
    在全局settings中添加此app
  3. 在users的urls中配置
from django.urls import path

from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = [
    path('login/', obtain_jwt_token),
]

  1. 创建一个超级管理员:python manage.py createsuperuser
    在这里插入图片描述
    会在表auth_user中创建一条数据:
    在这里插入图片描述

  2. 调用登录接口
    在这里插入图片描述
    返回数据中只有token,要是想要返回其它数据,则重写jwt_response_payload_handler方法


def jwt_response_payload_handler(token, user=None, request=None):
    return {
    
    
        'user_id': user.id,
        'username': user.username,
        'token': token
    }

然后,在全局settings中配置引用

JWT_AUTH = {
    
    
    # JWT响应处理器
    'JWT_RESPONSE_PAYLOAD_HANDLER':'utils.jwt_handle.jwt_response_payload_handler',
    # 'JWT_RESPONSE_PAYLOAD_HANDLER':'rest_framework_jwt.utils.jwt_response_payload_handler',

    # jwt前缀
    'JWT_AUTH_HEADER_PREFIX': 'JWT',

    # 到期时间
    'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300)
}

结果:
在这里插入图片描述

  1. 权限配置:在全局settings中配置
REST_FRAMEWORK={
    
    
    ...
    ...
    ...
    # 全局的认证方式
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # token认证
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        # 使用账号密码认证
        'rest_framework.authentication.BasicAuthentication'
    ],
    # 全局的权限配置
    'DEFAULT_PERMISSION_CLASSES': [
        # 默认是所有权限
        # 'rest_framework.permissions.AllowAny',
        # 只有登录用户才可以访问接口
        'rest_framework.permissions.IsAuthenticated',
        # 只有超级管理员才可以访问
        # 'rest_framework.permissions.IsAdminUser'
        # 如果没登录,只能获取数据,如果登录成功,就具备任意权限
        # 'rest_framework.permissions.IsAuthenticatedOrReadOnly'
    ],
}

访问其它接口时就必须带上token,如下结果:
在这里插入图片描述

二.场景二:注册

在users中的serializers.py中

from rest_framework import serializers,validators

from django.contrib.auth.models import User
from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler


class RegisterSerializer(serializers.ModelSerializer):
    password_confirm = serializers.CharField(label='确认密码', help_text='确认密码',
                                             min_length=6, max_length=20,
                                             write_only=True,
                                             error_messages={
    
    
                                                 'min_length': '仅允许6~20个字符的确认密码',
                                                 'max_length': '仅允许6~20个字符的确认密码', })
    token = serializers.CharField(label='生成token', read_only=True)

    class Meta:
        model = User
        fields = ('id', 'username', 'password', 'email', 'password_confirm', 'token')
        extra_kwargs = {
    
    
            'username': {
    
    
                'label': '用户名',
                'help_text': '用户名',
                'min_length': 6,
                'max_length': 20,
                'error_messages': {
    
    
                    'min_length': '仅允许6-20个字符的用户名',
                    'max_length': '仅允许6-20个字符的用户名',
                }
            },
            'email': {
    
    
                'label': '邮箱',
                'help_text': '邮箱',
                'write_only': True,
                'required': True,
                # 添加邮箱重复校验
                'validators': [validators.UniqueValidator(queryset=User.objects.all(), message='此邮箱已注册')],
            },
            'password': {
    
    
                'label': '密码',
                'help_text': '密码',
                'write_only': True,
                'min_length': 6,
                'max_length': 20,
                'error_messages': {
    
    
                    'min_length': '仅允许6-20个字符的密码',
                    'max_length': '仅允许6-20个字符的密码',
                }
            }
        }

    # 多字段校验:直接使用validate,但是必须返回attrs
    def validate(self, attrs):
        if attrs.get('password') != attrs.get('password_confirm'):
            raise serializers.ValidationError('密码与确认密码不一致')
        return attrs

    def create(self, validated_data):
        validated_data.pop('password_confirm')
        # 创建user模型对象
        user = User.objects.create_user(**validated_data)

        # 创建token
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        user.token = token
        return user

users/views.py中

注意需要指定permission_classes = []为空列表或者允许所有权限[rest_framework.permissions.AllowAny],因为此接口不需要任何认证就可访问

from rest_framework import generics
from users.serializers import RegisterSerializer

class UserView(generics.CreateAPIView):
    serializer_class = RegisterSerializer
    # 注意需要指定permission_classes = []为空列表或者允许所有权限[rest_framework.permissions.AllowAny]
    permission_classes = []

users/urls.py中

from django.urls import path,include

from rest_framework_jwt.views import obtain_jwt_token
from .views import UserView

urlpatterns = [
    path('login/', obtain_jwt_token),
    path('register/',UserView.as_view())
]

结果如图所示
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43534980/article/details/111462286