zoukankan      html  css  js  c++  java
  • Python学习————jwt

    jwt (json web token)

    控制用户登录才能访问,以及不登陆访问:

    # 1 控制用户登录后才能访问,和不登录就能访问
    from rest_framework.permissions import IsAuthenticated
    class OrderAPIView(APIView):# 登录才能
        authentication_classes = [JSONWebTokenAuthentication,]
        # 权限控制
        permission_classes = [IsAuthenticated,]
        def get(self,request,*args,**kwargs):
            return Response('这是订单信息')
    
    
    class UserInfoAPIView(APIView):# 不登录就可以
        authentication_classes = [JSONWebTokenAuthentication,]
        # 权限控制
        # permission_classes = [IsAuthenticated,]
        def get(self,request,*args,**kwargs):
            return Response('UserInfoAPIView')
    

    控制登录接口返回的数据格式:

    登录接口返回的数据格式
    1 第一种方案,自己写登录接口
    2 第二种方案,用内置方法,控制登录接口返回的数据格式
      -jwt的配置信息有这个属性
       ‘ JWT_RESPONSE_PAYLOAD_HANDLER’:
       ‘rest_framework_jwt.utils.jwt_response_payload_handler’
       重写jwt_response_payload_handler
    

    自定义基于jwt的权限类:

    # 3 自定义基于jwt的权限类
    from rest_framework.authentication import BaseAuthentication  # 基于它
    from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication # 基于它
    from rest_framework.exceptions import AuthenticationFailed
    # from rest_framework_jwt.authentication import jwt_decode_handler
    from rest_framework_jwt.utils import jwt_decode_handler # 跟上面是一个
    import jwt
    
    from api import models
    # class MyJwtAuthentication(BaseAuthentication):
    #     def authenticate(self, request):
    #         jwt_value=request.META.get('HTTP_AUTHORIZATION')
    #         if jwt_value:
    #             try:
    #             #jwt提供了通过三段token,取出payload的方法,并且有校验功能
    #                 payload=jwt_decode_handler(jwt_value)
    #             except jwt.ExpiredSignature:
    #                 raise AuthenticationFailed('签名过期')
    #             except jwt.InvalidTokenError:
    #                 raise AuthenticationFailed('用户非法')
    #             except Exception as e:
    #                 # 所有异常都会走到这
    #                 raise AuthenticationFailed(str(e))
    #             # 因为payload就是用户信息的字典
    #             print(payload)
    #             # return payload, jwt_value
    #             # 需要得到user对象,
    #             # 第一种,去数据库查
    #             # user=models.User.objects.get(pk=payload.get('user_id'))
    #             # 第二种不查库
    #             user=models.User(id=payload.get('user_id'),username=payload.get('username'))
    #             return user,jwt_value
    #         # 没有值,直接抛异常
    #         raise AuthenticationFailed('您没有携带认证信息')
    
    
    class MyJwtAuthentication(BaseJSONWebTokenAuthentication):
        def authenticate(self, request):
            jwt_value=request.META.get('HTTP_AUTHORIZATION')
            if jwt_value:
                try:
                #jwt提供了通过三段token,取出payload的方法,并且有校验功能
                    payload=jwt_decode_handler(jwt_value)
                except jwt.ExpiredSignature:
                    raise AuthenticationFailed('签名过期')
                except jwt.InvalidTokenError:
                    raise AuthenticationFailed('用户非法')
                except Exception as e:
                    # 所有异常都会走到这
                    raise AuthenticationFailed(str(e))
                user=self.authenticate_credentials(payload)
                return user,jwt_value
            # 没有值,直接抛异常
            raise AuthenticationFailed('您没有携带认证信息')
    

    手动签发token(多方式登录)

    # 使用用户名,手机号,邮箱,都可以登录#
    # 前端需要传的数据格式
    {
    "username":"lqz/1332323223/33@qq.com",
    "password":"lqz12345"
    }
    # 视图
    from rest_framework.views import APIView
    from rest_framework.viewsets import ViewSetMixin, ViewSet
    
    from app02 import ser
    class Login2View(ViewSet):  # 跟上面完全一样
        def login(self, request, *args, **kwargs):
            # 1 需要 有个序列化的类
            login_ser = ser.LoginModelSerializer(data=request.data,context={'request':request})
            # 2 生成序列化类对象
            # 3 调用序列号对象的is_validad
            login_ser.is_valid(raise_exception=True)
            token=login_ser.context.get('token')
            # 4 return
            return Response({'status':100,'msg':'登录成功','token':token,'username':login_ser.context.get('username')})
        
    # 序列化类
    from rest_framework import serializers
    from api import models
    import re
    from rest_framework.exceptions import ValidationError
    
    from rest_framework_jwt.utils import jwt_encode_handler,jwt_payload_handler
    class LoginModelSerializer(serializers.ModelSerializer):
        username=serializers.CharField()  # 重新覆盖username字段,数据中它是unique,post,认为你保存数据,自己有校验没过
        class Meta:
            model=models.User
            fields=['username','password']
    
        def validate(self, attrs):
    
            print(self.context)
    
            # 在这写逻辑
            username=attrs.get('username') # 用户名有三种方式
            password=attrs.get('password')
            # 通过判断,username数据不同,查询字段不一样
            # 正则匹配,如果是手机号
            if re.match('^1[3-9][0-9]{9}$',username):
                user=models.User.objects.filter(mobile=username).first()
            elif re.match('^.+@.+$',username):# 邮箱
                user=models.User.objects.filter(email=username).first()
            else:
                user=models.User.objects.filter(username=username).first()
            if user: # 存在用户
                # 校验密码,因为是密文,要用check_password
                if user.check_password(password):
                    # 签发token
                    payload = jwt_payload_handler(user)  # 把user传入,得到payload
                    token = jwt_encode_handler(payload)  # 把payload传入,得到token
                    self.context['token']=token
                    self.context['username']=user.username
                    return attrs
                else:
                    raise ValidationError('密码错误')
            else:
                raise ValidationError('用户不存在')
    

    jwt的配置参数

    # jwt的配置
    import datetime
    JWT_AUTH={
        'JWT_RESPONSE_PAYLOAD_HANDLER':'app02.utils.my_jwt_response_payload_handler',
        'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7), # 过期时间,手动配置
    }
    

    基于角色的权限控制(django内置auth体系)

    # RBAC :是基于角色的访问控制(Role-Based Access Control ),公司内部系统
    # django的auth就是内置了一套基于RBAC的权限系统
    
    # django中
    	# 后台的权限控制(公司内部系统,crm,erp,协同平台)
    	user表
        permssion表
        group表
        user_groups表是user和group的中间表
        group_permissions表是group和permssion中间表
        user_user_permissions表是user和permission中间表
        # 前台(主站),需要用三大认证
    # 演示:
    	
    	
    

    django缓存

    # 前端混合开发缓存的使用
    	-缓存的位置,通过配置文件来操作(以文件为例)
        -缓存的粒度:
        	-全站缓存
            	中间件
                MIDDLEWARE = [
                    'django.middleware.cache.UpdateCacheMiddleware',
                    。。。。
                    'django.middleware.cache.FetchFromCacheMiddleware',
                ]
                CACHE_MIDDLEWARE_SECONDS=10  # 全站缓存时间
            -单页面缓存
            	在视图函数上加装饰器
                from django.views.decorators.cache import cache_page
                @cache_page(5)  # 缓存5s钟
                def test_cache(request):
                    import time
                    ctime=time.time()
                    return render(request,'index.html',context={'ctime':ctime})
            	
            -页面局部缓存
            	{% load cache %}
                {% cache 5 'name' %}  # 5表示5s钟,name是唯一key值
                 {{ ctime }}
                {% endcache %}
            	
        
    # 前后端分离缓存的使用
    	- 如何使用
            from django.core.cache import cache
            cache.set('key',value可以是任意数据类型)
            cache.get('key')
        -应用场景:
        	-第一次查询所有图书,你通过多表联查序列化之后的数据,直接缓存起来
            -后续,直接先去缓存查,如果有直接返回,没有,再去连表查,返回之前再缓存
    
    
  • 相关阅读:
    Laravel 5.2 使用 JWT 完成多用户认证 | Laravel China 社区
    (上线时清缓存)laravel 5.1 的程序性能优化(配置文件)
    linux计划任务及压缩归档
    用户及用户管理
    vim编辑器
    linux进阶命令
    权限管理
    linux基础命令2
    linu基础命令1
    连接Xshell
  • 原文地址:https://www.cnblogs.com/x945669/p/13307611.html
Copyright © 2011-2022 走看看