zoukankan      html  css  js  c++  java
  • DRF-JWT

    DRF-JWT

    一、JWT

    • JWT全称: json web token,

    • 作用:将原始的数据json加密成字符串,通过后台将加密的字符串给前台存储(token)

    • 格式:三段式,头.载荷.签名 , 头和载荷都是采用base34可逆加密,签名采用md5不可逆加密

      • 头(基础信息,也可以为空):加密方式、公司信息、项目中信息....
      • 载荷(核心信息): 用户信息、过期时间...
      • 签名(安全保障): 头加密结果+载荷加密结果+服务器秘钥的md5加密的结果
      • 注意:后台一定要保障服务器秘钥的安全,他是jwt唯一安全保障,后台签发token -> 前台存储 -> 发送需要认证的请求带着token -> 后台校验得到合法的用户
    • jwt认证优点:

      • 后台不需要存储token,只需要存储签发与校验tokne的算法,效率远远大于后台存储和取出完成token的校验
      • jwt算法认证,更适合服务器集群的部署
    • 采用drf-jwt框架,后期任务主需要书写登录,drf-jwt只完成了账号密码登录,我们还需要手机登录,邮箱登录,不需要重写认证类,因为认证规则已经完成且固定不变,变得只有认证字符串的前缀,前缀可以在配置文件中配置

    二、jwt模块安装

    # 安装
    >:pip install djangorestframework-jwt
    # 模块
    rest_framework_jwt
    

    三、前后端分离模式下信息交互规则

    1. 任何人都可以直接访问的接口

      请求不论是get、还是post请求方式,不需要任何的校验

    2. 必须登录后才能访问接口

      任何请求方式都进行限制,请求中必须在请求头中携带认证信息 - authorization

    3. 前台认证信息获取只能通过登录接口

      前台提供账号和密码等信息,到后台进行校验返回认证信息token加密字符串

    4. 前台如何完成注销

      前台登录成功一般在cookie中保存认证信息token,登录注销就是前台主动清除保存的token加密字符串信息

    四、jwt模块使用

    4.1全局配置

    # rest_framework全局配置 认证
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication'
    ],
    
    # jwt认证类配置
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ],
    
    # 局部禁用
    authentication_classes = [] # 
    
    
    
    # 局部启用
    from user.authentications import JSONWebTokenAuthentication
    authentication_classes = [JSONWebTokenAuthentication]
    

    只需将rest_framework全局配置认证改成JWT认证

    4.2 token过期时间配置

    # drf-jwt配置
    import datetime
    JWT_AUTH = {
        # 过期时间,生成的took七天之后不能使用
        'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
    	# 刷新时间 之后的token时间值
        # 'JWT_ALLOW_REFRESH': True,
        'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
    	# 请求头携带的参数
        'JWT_AUTH_HEADER_PREFIX': 'JWT',
    }
    
    
    
    

    4.3JWT认证使用

    from django.conf.urls import url
    from . import views
    from rest_framework_jwt.views import ObtainJSONWebToken,obtain_jwt_token,verify_jwt_token,refresh_jwt_token
    urlpatterns = [
        # url(r'^admin/', admin.site.urls),
        url(r'^test/', views.TestAPIview.as_view()),
        url(r'^user/', views.UserListAPIView.as_view()),
        url(r'^login/', views.LoginAPIView.as_view()),
    
        # jwt认证
        # url(r'^jwt/login/', views.JwtLoginAPIView.as_view()),
        url(r'^jwt/login/$', views.JwtLoginAPIView.as_view()),
        url(r'^jwt/center/$', views.JwtUserCenterAPIView.as_view()),
    
    ]
    

    1.多方登录认证

    # url.py
    url(r'^login/$', views.LoginAPIView.as_view()),
    url(r'^user/center/$', views.UserCenterAPIView.as_view()),
    # 1. 反序列化类.py
    from rest_framework.serializers import ModelSerializer, CharField, ValidationError, SerializerMethodField
    from . import models
    from django.contrib.auth import authenticate
    import re
    
    from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
    class LoginSerializer(ModelSerializer):
        username = CharField(write_only=True)
        password = CharField(write_only=True)
        class Meta:
            model = models.User
            fields = ('username', 'password')
        # 在全局钩子中签发token
        def validate(self, attrs):
            # user = authenticate(**attrs)V
            # 账号密码登录 => 多方式登录
            user = self._many_method_login(**attrs)
            # 签发token,并将user和token存放到序列化对象中
            payload = jwt_payload_handler(user)  # 获取用户信息
            token = jwt_encode_handler(payload) # 生成token
            self.user = user
            self.token = token
            return attrs
    
        # 多方式登录
        def _many_method_login(self, **attrs):
            username = attrs.get('username')
            password = attrs.get('password')
            if re.match(r'.*@.*', username):
                user = models.User.objects.filter(email=username).first()  # type: models.User
            elif re.match(r'^1[3-9][0-9]{9}$', username):
                user = models.User.objects.filter(mobile=username).first()
            else:
                user = models.User.objects.filter(username=username).first()
    
            if not user:
                raise ValidationError({'username': '账号有误'})
    
            if not user.check_password(password):
                raise ValidationError({'password': '密码有误'})
    
            return user
    
    # 2.view.py
    from rest_framework.views import APIView
    from . import models, serializers
    from utils.response import APIResponse
    class LoginAPIView(APIView):
        authentication_classes = []
        permission_classes = []
        def post(self, request, *args, **kwargs):
            serializer = serializers.LoginSerializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            return APIResponse(msg='login success', data={
                'username': serializer.user.username,
                'token': serializer.token
            })
    

    1574770371521

    4.2 获取用户信息

    # 序列化类.py
    class JwtUserModelSerializer(serializers.ModelSerializer):
        password = serializers.SerializerMethodField()
    
        def get_password(self, obj):
            return "#########"
    
        class Meta:
            model = models.User
            fields = ('username', 'password',  'email', 'first_name', 'last_name')
    # view.py
    class JwtUserCenterAPIView(APIView):
        # 权限认证
        permission_classes = [IsAdminUser]
    	
        def get(self, request, *args, **kwargs):
            user = request.user
            serializer_obj = serializers.JwtUserModelSerializer(user)
    
            return APIResponse(data=serializer_obj.data)
    
    

    1574770526530

    五、总结

    jwt模块使用:

    1. 使用jwt模块认证的时候需要在全局配置认证使用的是jwt的认证模块
    2. 可以设置token的过期时间,在setting.py中配置
  • 相关阅读:
    C语言I博客作业05 sun
    C语言I博客作业08 sun
    C语言I博客作业02 sun
    C语言I博客作业04 sun
    elastix的web端口修改
    mysql.proc错误解决
    Client.Error.MessageSend 错误解决方案
    让secureCRT正确显示中文
    elastix的多个inbound route的设置
    PHP5.1时间相差8小时问题解决。
  • 原文地址:https://www.cnblogs.com/randysun/p/12293036.html
Copyright © 2011-2022 走看看