• JWT


    JWT

    """
    1、组成: 
    header.payload.signature 头.载荷.签名
    
    2、距离:
    eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6Im93ZW4iLCJleHAiOjE1NTgzMDM1NDR9.4j5QypLwufjpqoScwUB9LYiuhYcTw1y4dPrvnv7DUyo
    
    3:介绍:
    header:一般存放如何处理token的方式:加密的算法、是否有签名等
    payload:数据的主体部分:用户信息、发行者、过期时间等
    signature:签名:将header、payload再结合密码盐整体处理一下
    """
    

    工作原理

    """
    1) jwt = base64(头部).base64(载荷).hash256(base64(头部).base(载荷).密钥)
    2) base64是可逆的算法、hash256是不可逆的算法
    3) 密钥是固定的字符串,保存在服务器
    """
    

    drf-jwt

    官网
    https://github.com/jpadilla/django-rest-framework-jwt
    
    安装子:虚拟环境
    pip install djangorestframework-jwt
    
    使用:user/urls.py
    from django.urls import path
    from rest_framework_jwt.views import obtain_jwt_token
    urlpatterns = [
        path('login/', obtain_jwt_token),
    ]
    
    测试接口:post请求
    """
    postman发生post请求
    
    接口:http://api.luffy.cn:8000/user/login/
    
    数据:
    {
    	"username":"admin",
    	"password":"admin"
    }
    """
    

    drf-jwt开发

    配置信息:JWT_AUTH到dev.py中
    import datetime
    JWT_AUTH = {
        # 过期时间
        'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
        # 自定义认证结果:见下方序列化user和自定义response
        'JWT_RESPONSE_PAYLOAD_HANDLER': 'user.utils.jwt_response_payload_handler',  
    }
    
    序列化user:user/serializers.py(自己创建)
    from rest_framework import serializers
    from .models import User
    class UserModelSerializer(serializers.ModelSerializer):
        """轮播图序列化器"""
        class Meta:
            model = User
            fields = ["username", "mobile"]
    
    自定义response:user/utils.py
    from .serializers import UserModelSerializers
    def jwt_response_payload_handler(token, user=None, request=None):
        return {
            'token': token,
            'user': UserModelSerializer(user).data
        }
        # restful 规范
        # return {
        #     'status': 0,
        #     'msg': 'OK',
        #     'data': {
        #         'token': token,
        #         'username': user.username
        #     }
        # }
    
    
    基于drf-jwt的全局认证:user/authentications.py(自己创建)
    import jwt
    from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication
    from rest_framework.authentication import get_authorization_header
    from rest_framework_jwt.settings import api_settings
    from rest_framework.exceptions import AuthenticationFailed
    from rest_framework_jwt.authentication import jwt_decode_handler
    class JSONWebTokenAuthentication(BaseJSONWebTokenAuthentication):
        def authenticate(self, request):
            # 利用drf获取认证的token,来自请求头的Authorization字段
            jwt_value = get_authorization_header(request)
            # 自定义从请求头的某个字段得到认证的token
            # jwt_value = request.META.get('HTTP_TOKEN', b'')
    
            # 反扒策略
            jwt_value_list = jwt_value.split()
            if len(jwt_value_list) != 2:
                raise AuthenticationFailed('太长或太短,认证失败')
            if jwt_value_list[0].lower().decode() != api_settings.JWT_AUTH_HEADER_PREFIX.lower():
                raise AuthenticationFailed('没头,认证失败')
            jwt_value = jwt_value_list[1]
    
            try:
                payload = jwt_decode_handler(jwt_value)
            except jwt.ExpiredSignature:
                raise AuthenticationFailed('过期了,认证失败')
            except jwt.InvalidTokenError:
                raise AuthenticationFailed('非法用户,认证失败')
    
            user = self.authenticate_credentials(payload)
    
            return (user, jwt_value)
    
    
    全局启用:settings/dev.py
    REST_FRAMEWORK = {
        # 认证模块
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'user.authentications.JSONWebTokenAuthentication',
        ),
    }
    
    
    局部启用禁用:任何一个cbv类首行
    # 局部禁用
    authentication_classes = []
    
    # 局部启用
    from user.authentications import JSONWebTokenAuthentication
    authentication_classes = [JSONWebTokenAuthentication]
    
    
    多方式登录:user/utils.py
    from django.contrib.auth.backends import ModelBackend
    from .models import User
    import re
    class JWTModelBackend(ModelBackend):
        def authenticate(self, request, username=None, password=None, **kwargs):
            """
            :param request:
            :param username: 前台传入的用户名
            :param password: 前台传入的密码
            :param kwargs:
            :return:
            """
            try:
                if re.match(r'^1[3-9]d{9}$', username):
                    user = User.objects.get(mobile=username)
                elif re.match(r'.*@.*', username):
                    user = User.objects.get(email=username)
                else:
                    user = User.objects.get(username=username)
            except User.DoesNotExist:
                return None  # 认证失败就返回None即可,jwt就无法删除token
            # 用户存在,密码校验通过,是活着的用户 is_active字段为1
            if user and user.check_password(password) and self.user_can_authenticate(user):
                return user  # 认证通过返回用户,交给jwt生成token
    
    
    配置多方式登录:settings/dev.py
    AUTHENTICATION_BACKENDS = ['user.utils.JWTModelBackend']
    
    
    手动签发JWT:了解 - 可以拥有原生登录基于Model类user对象签发JWT
    from rest_framework_jwt.settings import api_settings
    
    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)
    
    
    # 了解,原生视图
    # 原生APIView可以实现手动签发 jwt
    class LoginAPIView(APIView):
        def post(self):
            # 完成手动签发
            pass
    
    
  • 相关阅读:
    201521123098 《Java程序设计》 第5周学习总结
    201521123098 《Java程序设计》 第4周学习总结
    201521123098 《Java程序设计》第3周学习总结
    Beta阶段Scrum 冲刺博客合集
    项目复审——Alpha阶段
    事后诸葛亮分析
    展示博客
    测试与发布
    Alpha阶段敏捷冲刺总结
    敏捷冲刺七
  • 原文地址:https://www.cnblogs.com/king-home/p/11233992.html
Copyright © 2020-2023  润新知