ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

day 87 jwt 、 手动签发token、jwt的配置参数、 基于角色的权限控制、 django缓存

2022-02-04 16:05:11  阅读:318  来源: 互联网

标签:username get jwt payload token user import 87


昨日内容回顾

# 1 自定义频率类
# 2 自动生成接口文档
# 3 jwt:三部分组成: 头+荷载(用户数据)+签名
# 4 drf中使用jwt:djangorestframework_jwt
	-路由里配了一个
    -

# 4 补充base64使用

今日内容

1 jwt

# 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')
# 2 控制登录接口返回的数据格式
	-第一种方案,自己写登陆接口
    -第二种写法,用内置,控制登陆接口返回数据格式
    	    'JWT_RESPONSE_PAYLOAD_HANDLER':
    'rest_framework_jwt.utils.jwt_response_payload_handler',
    	-重写jwt_response_payload_handler,配置成自己的
# 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 serz
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的配置参数

# 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_permission表是group和permission中间表
    user_user_permission表是user和permission中间表
    # 前台(主站), 需要用三大认证
# 演示

3 django缓存

# 前后端混合开发缓存的使用
	-缓存位置,通过配置文件来操作(以文件为例)
    -缓存的粒度
    	-全站缓存
        	中间件
              MIDDLEWARE = [
                'django.middleware.cache.UpdateCacheMiddleware',
                。。。。
                'django.middleware.cache.FetchFromCacheMiddleware',
            	]
        -单页面缓存
        	在视图函数上加装饰器
            @cache_page(5) # 表示缓存5秒钟
            def text_cache(request):
                import time
                ctime = time.time()
                return render(request, 'index.html', context={'ctime': ctime})

        -页面局部缓存
        	{% load cache %}
            {% cache 5 'name' %} # 5表示5秒钟, name是唯一key值
            {{ ctime }}
            {% endcache %}
# 前后端分离缓存的使用
	- 如何使用
        from django.core.cache import cache
        cache.set('key', value可以是任意数据类型)
        cache.get('key')
    -应用场景
    	-第一次查询所有图书,你通过多表联查序列化之后的数据,直接缓存起来
    	-后续,直接先去缓存查,如果有直接返回,没有,再去联表查,返回之前在缓存
  

标签:username,get,jwt,payload,token,user,import,87
来源: https://www.cnblogs.com/md-my/p/15862883.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有