jwt,认证,分页
jwt
# jwt: json web tokens # jwt规范:就是对token的规范,头.体.签名 ''' 1.token一定是后台产生,拥有请求认证,所以要前后台统一 2.token的组成部分通常有三分部组成:header.payload.signature 3.header:{"token的加密方式": "base64", "是否有签名": True} 加密处理后的结果 4.payload:{"账号": *, "密码": *, "发行者": *, "过期时间": *, "浏览器信息": *} 加密处理后的结果 5.signature:{"header": *, "payload": *, "salt": *} 加密处理后的结果 eg: eyJ0eXAiOiJK.eyJ1c2VyX2lkIjoxLCJ1cNTgzMDM1NDR9.4j5QypLwuf '''
# 安装 djangorestframework-jwt # -- pip3 install djangorestframework-jwt # 采用 djangorestframework-jwt框架 产生 jwt规范的 token from rest_framework_jwt.settings import api_settings def get_jwt_token(user): # 自定义生成token,基于某user对象,且该user对象必须有username、password两个字段 jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER payload = jwt_payload_handler(user) token = jwt_encode_handler(payload) return token
# token可以存储的位置:服务器、缓存、客户端 # 1.产生token: 对request操作形成 header.payload.signature def token_encode(request): token = "" print(request) # 加密规则 # 将request变成 "header.payload.signature" header_dic = { "lock_code": "base64" } header = base64.b64encode(json.dumps(header_dic).encode('utf-8')) payload = b"abc123" signature = b"000" token_data = b"%s.%s.%s" % (header, payload, signature) token = token_data.decode('utf-8') return token # 在登录时,用token_encode产生token,丢给前台即可,服务器不用存储 # 2.解析token:从request中的token 解析出 header、payload、signature def token_decode(request): token = request.META.get('HTTP_TOKEN') # type: str header, payload, signature = token.split('.') # 解密规则 # header校验,失败 # return None header_str = base64.b64decode(header.encode('utf-8')) header_dic = json.loads(header_str) if header_dic != {"lock_code": "base64"}: return None # payload校验,失败 # return None # signature校验,失败 # return None # 校验成功 # return user, auth # 在认证模块校验时,用token_decode校验token,不是查询UserToken数据库校验
# app.models class User(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=32) # 用户有不同的权限分类 level = models.IntegerField(choices=((0, '普通用户'), (1, '超级用户')), default=0) # app.auth from rest_framework.permissions import BasePermission class VisitPermission(BasePermission): message = '验证失败:权限不够!' def has_permission(self, request, view): # 1)拿到登录的用户 user = request.user # 2)获取用户的权限 # lever = user.level lever_str = user.get_level_display() # 3)权限判断 if lever_str == '超级用户': return True # 验证通过 return False # 验证失败 # app.views from app import auth class Books(APIView): permission_classes = [auth.VisitPermission] # 局部使用 def get(self, request): return Response({ "status": 0, "msg": 'get books success', "results": [], "user_name": request.user.username }) # 了解:全局使用局部禁用 # settings REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': ( 'app.auth.VisitPermission', ) } # views class Books(APIView): permission_classes = [] # 局部禁用
# 项目开发 # app.auth from rest_framework.throttling import SimpleRateThrottle class VisitRateThrottle(SimpleRateThrottle): scope = "luffy" def get_cache_key(self, request, view): return self.get_ident(request) # return request.META.get('REMOTE_ADDR') # 对IP进行频率限制 # return request.user.username # 对用户进行频率限制 # settings REST_FRAMEWORK = { # 频率的配置 3/s 3/m 3/h 3/h 'DEFAULT_THROTTLE_RATES': { 'luffy': '3/m' # 一分钟可以访问三次 } # 全局配置 'DEFAULT_THROTTLE_CLASSES': ( 'app.auth.VisitRateThrottle', ) } # views class Books(APIView): # 局部禁用 throttle_classes = []
class MyThrottle(BaseThrottle): # 存放ip与访问时间list的对应关系 VISIT_RECORD = {} def __init__(self): # 存放某一访问者历史访问时间的 self.history = None def allow_request(self, request, view): # 1) 取出访问者ip ip = request.META.get('REMOTE_ADDR') # 2) 获取当前时间 import time ctime = time.time() # 3) 判断是否是第一次访问 if ip not in self.VISIT_RECORD: self.VISIT_RECORD[ip] = [ctime, ] return True self.history = self.VISIT_RECORD.get(ip) # 4) 当前时间与最开始访问时间间隔超出60s则可以再次访问,移除最开始的访问时间 while self.history and ctime - self.history[-1] > 60: self.history.pop() # 5) 访问频率的处理 if len(self.history) < 3: self.history.insert(0, ctime) return True else: return False def wait(self): import time ctime = time.time() # 还要等多久才能访问 return 60 - (ctime - self.history[-1])
# models class Teacher(models.Model): name = models.CharField(max_length=32) salary = models.DecimalField(max_digits=5, decimal_places=2) # objson class TeacherJson(serializers.ModelSerializer): class Meta: model = models.Teacher fields = '__all__' # urls url(r'^teachers/', views.Teachers.as_view()), # views class Teachers(APIView): def post(self, request): list = [] for i in range(1, 51): list.append(models.Teacher(name="%s老师" % i, salary=i)) models.Teacher.objects.bulk_create(list) return Response({ 'status': 0, 'msg': 'ok' })
from rest_framework.pagination import PageNumberPagination class Teachers(APIView): permission_classes = [] throttle_classes = [] throttle_classes = [] def get(self, request): # 没有分页的所有数据 teacher_list = models.Teacher.objects.all() # 完成分页 # 1) 初始化分页对象 page_simple = PageNumberPagination() # 2) 配置分页对象 # page_simple.page_size = api_settings.PAGE_SIZE # 一页显示的条数 page_simple.page_size = 5 # /teachers/?pages=3 默认page page_simple.page_query_param = 'pages' # /teachers/?pages=3&line=10 用户可以自定义访问一页有多少条数据 page_simple.page_size_query_param = 'line' # 限制用户自定义一页最大能访问的条数 page_simple.max_page_size = 10 # 3) 操作分页后一页的数据 teacher_page_list = page_simple.paginate_queryset(teacher_list, request, self) # 将一页的数据序列化后返回给前台 teacher_data = objson.TeacherJson(teacher_page_list, many=True).data return Response({ 'status': 0, 'msg': 'ok', 'results': teacher_data })
from rest_framework.pagination import LimitOffsetPagination class Teachers(APIView): def get(self, request): teacher_list = models.Teacher.objects.all() # 完成分页 # 1) 初始化分页对象 page_limit = LimitOffsetPagination() # 2) 配置分页对象 # 一页显示的条数 page_limit.default_limit = 5 # 自定义一页获取的条数 page_limit.limit_query_param = 'limit' # 从哪条数据开始查询 page_limit.offset_query_param = 'offset' # 自定义最大获取一页的条数 page_limit.max_limit = 8 # 3) 操作分页数据 teacher_page_list = page_limit.paginate_queryset(teacher_list, request, self) teacher_data = objson.TeacherJson(teacher_page_list, many=True).data return Response({ 'status': 0, 'msg': 'ok', 'previous': page_limit.get_previous_link(), # 上一页 'next': page_limit.get_next_link(), # 下一页 'results': teacher_data }) # return page_limit.get_paginated_response(teacher_data) # 内部提供的Response对象
from rest_framework.pagination import CursorPagination class Teachers(APIView): def get(self, request): teacher_list = models.Teacher.objects.all() # 完成分页 # 1) 初始化分页对象 page_cursor = CursorPagination() # 2) 配置分页对象 # 一页的条数 page_cursor.page_size = 10 # 排序的字段,可以正向也可以反向 page_cursor.ordering = '-id' # 游标的关键字 page_cursor.cursor_query_param = 'cursor' # 3) 操作分页数据 teacher_page_list = page_cursor.paginate_queryset(teacher_list, request, self) teacher_data = objson.TeacherJson(teacher_page_list, many=True).data return Response({ 'status': 0, 'msg': 'ok', 'previous': page_cursor.get_previous_link(), # 上一页 'next': page_cursor.get_next_link(), # 下一页 'results': teacher_data })


浙公网安备 33010602011771号