用户模块

Json Web Token认证

最常见的认证机制

Session认证
Token认证

Session认证
保持在服务端,增加服务器开销
分布式架构中,难以维持Session会话同步
CSRF攻击风险(跨站请求)

Token认证
保存在客户端
跨语言,跨平台
扩展性强
鉴权性能高

JWT(Json Web Token)

由三部分组成

header
声明类型
声明加密算法
base64加密,可以解密

playload
存放过期时间,签发用户等
可以添加用户的非敏感信息
base64加密,可以解密

signature
由三部分组成

使用base64加密之后的header + . + 使用base64加密之后的playload + 使用HS256算法加密,同时secret加盐处理

安装djangorestframework-jwt
pip install djangorestframework-jwt

在 setting.py中添加

REST_FRAMEWORK = {
    # 默认响应渲染类
    'DEFAULT_RENDERER_CLASSES': (
        # json渲染器为第一优先级
        'rest_framework.renderers.JSONRenderer',
        # 可浏览的API渲染器为第二优先级
        'rest_framework.renderers.BrowsableAPIRenderer',
    ),
    'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.OrderingFilter',
                                'django_filters.rest_framework.backends.DjangoFilterBackend'],
    # 在全局指定分页的引擎
     #'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'DEFAULT_PAGINATION_CLASS': 'utils.pagination.PageNumberPaginationManual',
    # 同时必须指定每页显示的条数
    # 'PAGE_SIZE': 3,
    'DEFAULT_AUTHENTICATION_CLASSES': [
		# 使用JWT Token认证
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
         # Basic类型的认证(账号和密码)
        'rest_framework.authentication.SessionAuthentication',
        # Session会话认证
        'rest_framework.authentication.BasicAuthentication'
    ],
}

添加路由
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()),
]

主路由添加

urlpatterns = [
		 path('user/', include('user.urls')),]

登录成功
在这里插入图片描述Token 第一段header 和 第二段playload載荷解密
注意第二段解密的时候如果位数不足需要在最后面添加一个或者两个 “=”

import base64
token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyLCJ1c2VybmFtZSI6ImxpdXdlaTExIiwiZXhwIjoxNjAyODEwMTQxLCJlbWFpbCI6IjU4OUBxcS5jb20ifQ.sM2LIPmUL7jvOBx1dO4eutVgb3bt1vcu1AVruOgGXtY"

a = base64.b64decode('eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9')
print(a) #b'{"typ":"JWT","alg":"HS256"}'

b = base64.b64decode('eyJ1c2VyX2lkIjoyLCJ1c2VybmFtZSI6ImxpdXdlaTExIiwiZXhwIjoxNjAyODEwMTQxLCJlbWFpbCI6IjU4OUBxcS5jb20ifQ==')
print(b)#b'{"user_id":2,"username":"liuwei11","exp":1602810141,"email":"589@qq.com"}'

认证过期时间的修改
./site-packages/rest_framework_jwt/settings.py 四十行代码

'JWT_EXPIRATION_DELTA':datetime.timedelta(seconds=300),#默认300s

在项目setting中修改,token时效,认证形式(默认JWT开头),登录成功后的返回内容(载客palyload)

JWT_AUTH = {
    # 默认5分钟过期, 可以使用JWT_EXPIRATION_DELTA来设置过期时间
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
    # 'JWT_AUTH_HEADER_PREFIX': 'B',#M默认是JWT
    'JWT_RESPONSE_PAYLOAD_HANDLER':
        'utils.jwt_handler.jwt_response_payload_handler',
}

playload源码只返回token(rest_framework_jwt.utils.jwt_response_payload_handler)

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
    }

重写jwt_response_payload_handler,在项目的setting中JWT_AUTH指定(见上面):

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

Django自带的用户模型
django.contrib.auth.models.User
在这里插入图片描述查看settings.py可以发现,默认注册了 django.contrib.auth,User的model就在这里面

在这里插入图片描述

**

注册

**

用户名(6-20位,不重复)
邮箱(符合邮箱格式)
密码(6-20位,和确认密码一致)
确认密码(6-20位,和密码一致

user/serializers.py


from rest_framework import serializers
from django.contrib.auth.models import User
from rest_framework_jwt.settings import api_settings


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)
    #因为User 的model中没有password_confirm 和token 所以要在这上面指定校验

    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,
            },
            '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):
        password = attrs.get('password')
        password_confirm = attrs.get('password_confirm')
        if password != password_confirm:
            raise serializers.ValidationError('两次输入的密码不正确')
        return attrs


    def create(self, validated_data):
        validated_data.pop('password_confirm')
        user = User.objects.create_user(**validated_data)

        # 创建手动创建token,注册成功之后返回token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        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 serializers

class RegisterView(CreateAPIView):
    serializer_class = serializers.RegisterSerializer
    # authentication_classes = (JSONWebTokenAuthentication, )

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值