• JWT、多方式登录、django缓存


    ## 1 jwt

    ### 1.1 控制用户登录后才能访问,和不登录就能访问

    ```python
    # 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 控制登录接口返回的数据格式

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

    ## 1.3 自定义基于jwt的权限类

    ```python
    # 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('您没有携带认证信息')
    ```

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

    ```python
    # 使用用户名,手机号,邮箱,都可以登录#
    # 前端需要传的数据格式
    {
    "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('用户不存在')
    ```


    ## 1.5 jwt的配置参数

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


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

    ```python
    # 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中间表
    # 前台(主站),需要用三大认证
    # 演示:


    ```


    ## 3 django缓存

    ```python
    # 前端混合开发缓存的使用
    -缓存的位置,通过配置文件来操作(以文件为例)
    -缓存的粒度:
    -全站缓存
    中间件
    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')
    -应用场景:
    -第一次查询所有图书,你通过多表联查序列化之后的数据,直接缓存起来
    -后续,直接先去缓存查,如果有直接返回,没有,再去连表查,返回之前再缓存

    ```


    # 补充

    ## 1 补充base64使用

    ```python
    # base64编码和解码
    #md5固定长度,不可反解
    #base63 变长,可反解

    #编码(字符串,json格式字符串)
    import base64
    import json
    dic={'name':'lqz','age':18,'sex':'男'}
    dic_str=json.dumps(dic)

    ret=base64.b64encode(dic_str.encode('utf-8'))
    print(ret)

    # 解码
    # ret是带解码的串
    ret2=base64.b64decode(ret)
    print(ret2)
    ```
  • 相关阅读:
    Windows 10 版本 1507 中的新 AppLocker 功能
    github 查询
    Facebook Paper使用的第三方库
    C#如何使用右下角托盘图标notifyIcon
    C#如何设置窗体不能修改大小
    C#如何让Listbox支持多选
    C#如何开发多语言支持的Winform程序
    C#如何发布项目 发布软件
    C#如何编辑tab选项卡
    C#如何把写好的类编译成dll文件
  • 原文地址:https://www.cnblogs.com/0B0S/p/13618015.html
Copyright © 2020-2023  润新知