zoukankan      html  css  js  c++  java
  • 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)
    ```
  • 相关阅读:
    Python 集合
    Python sorted()
    CodeForces 508C Anya and Ghosts
    CodeForces 496B Secret Combination
    CodeForces 483B Friends and Presents
    CodeForces 490C Hacking Cypher
    CodeForces 483C Diverse Permutation
    CodeForces 478C Table Decorations
    CodeForces 454C Little Pony and Expected Maximum
    CodeForces 313C Ilya and Matrix
  • 原文地址:https://www.cnblogs.com/0B0S/p/13618015.html
Copyright © 2011-2022 走看看