zoukankan      html  css  js  c++  java
  • Django中使用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.exceptions import AuthenticationFailed
    from rest_framework_jwt.authentication import jwt_decode_handler
    from rest_framework_jwt.authentication import get_authorization_header
    from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication
    class JSONWebTokenAuthentication(BaseJSONWebTokenAuthentication):
            def authenticate(self, request):
                # 采用drf获取token的手段 - HTTP_AUTHORIZATION - Authorization
                token = get_authorization_header(request)
                if not token:
                    raise AuthenticationFailed('Authorization 字段是必须的')
                # 可以添加反扒措施:原功能是token有前缀
    
                # drf-jwt认证校验算法
                try:
                    payload = jwt_decode_handler(token)
                except jwt.ExpiredSignature:
                    raise AuthenticationFailed('签名过期')
                except jwt.InvalidTokenError:
                    raise AuthenticationFailed('非法用户')
                user = self.authenticate_credentials(payload)
                # 将认证结果丢该drf
                return user, token
    
    全局启用: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
    
  • 相关阅读:
    Speex for Android
    反射(高大上)、类的内置方法
    hashlib摘要算法模块,logging日志,configparser配置文件模块
    抽象类,接口类,封装,property,classmetod,statimethod
    面对对象三大特征:继承 多态(鸭子类型)(面试题)
    面向对象命名空间及组合(面试题)
    初始面向对象
    模块与包
    常用模块
    列表表达式,生成器表达式,
  • 原文地址:https://www.cnblogs.com/ruhai/p/11311852.html
Copyright © 2011-2022 走看看