Django--009 JWT和注册登陆

1. JWT

1.1 简介

  • 定义:JSON Web Token,目前最流行的跨域身份验证解决方案
  • 原理: 服务器身份验证之后,将生成一个JSON对象并将其发送回用户。当用户与服务器进行后续通信时,客户在请求中发回JSON对象。服务器仅依赖于这个JSON对象来标识用户。为了防止用户篡改数据,服务器将在生成对象时添加签名。
  • 优点: 服务器不保存任何会话数据,即服务器变为无状态,使其更容易扩展
  • 构成: header、playload、signature
    • header:声明类型、加密算法(默认HS256)、base64加密(可解密)
    • playload:存放过期时间、用户的非敏感信息、base64加密(可解密)
    • signature:base64加密后的header + base64加密后的playload + (HS256+secret)加密串

1.2 JWT使用

  • url配置
# user/urls.py

from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token


urlpatterns = [
    path('login/', obtain_jwt_token)
]
  • httpie访问
# 登陆,获取token
http :8000/user/login/ username=zy password=123456

http :8000/projects/ Authorization:"JWT token"

# 或者
http -a zy:123456 :8000/projects/ 

2. 登陆注册

2.1 注册需求

参数 输入/出 校验/描述
用户名 输入/出 6-20位,不能重复
邮箱 输入 合法格式,不能重复
密码 输入 6-20位,与确认密码一致
确认密码 输入 6-20位,与确认密码一致
token 输入 注册成功之后返回token

2.2 代码

  • Django 自带认证功能auth模块和User对象的基本操作
  • user模型需继承django自带的用户认证系统AbstractUser才可以使用
# user/serializer.py

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


class RegisterSerializer(serializers.ModelSerializer):
    password_confirm = serializers.CharField(label='确认密码', min_length=6, max_length=20, help_text='确认密码',
                                             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': [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个字符的密码',
                }
            }
        }

    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
        ## jwt_payload_handler--对payload加密
        payload = jwt_payload_handler(user)
        ## jwt_encode_handler--对三个部分加密生成token
        token = jwt_encode_handler(payload)

        user.token = token
        return user
# user/urls.py

from django.urls import path, include
from rest_framework_jwt.views import obtain_jwt_token
from . import views


urlpatterns = [
    path('login/', obtain_jwt_token),
    path('register/', views.RegisterView.as_view())
]
# user/views.py

from rest_framework.generics import CreateAPIView
from . import serializer


class RegisterView(CreateAPIView):
    serializer_class = serializer.RegisterSerializer
# utils/jwt_handler.py

def jwt_response_payload_handler(token, user=None, request=None):
    """
    Returns the response data for both the login and refresh views.
    Override to return a custom response such as including the
    serialized representation of the User.

    Example:

    def jwt_response_payload_handler(token, user=None, request=None):
        return {
            'token': token,
            'user': UserSerializer(user, context={'request': request}).data
        }

    """
    return {
    
    
        'token': token,
        'username': user.username,
        'user_id': user.id
    }
# settings.py

import datetime

JWT_AUTH = {
    
    
	# 设置token过期时间为1天
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
    # 修改JWT前缀,默认JWT
    'JWT_AUTH_HEADER_PREFIX': 'JWT',
    # 修改payload函数,取自定义
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'utils.jwt_handler.jwt_response_payload_handler',
}

Guess you like

Origin blog.csdn.net/qq_25672165/article/details/120345711
009