Django Rest Framework(一 认证、权限、节流使用示例)
路径:api\utils\auth.py
from test_restful import models from django.http import JsonResponse from rest_framework.request import Request from rest_framework import exceptions from rest_framework.authentication import BaseAuthentication class FirstAuthtication(BaseAuthentication): ''' 构建一个最基础的用户认证类,没有实际意义,仅用于熟悉它的使用方法 ''' def authenticate(self, request): token = request._request.GET.get('token') token_obj = models.UserToken.objects.filter(token=token).first() if not token_obj: raise exceptions.AuthenticationFailed('哎呀,没通过') # 返回元组,用于rest_freamwork 的后续操作 # token_obj.user是用户类的实例 token_obj是token类的实例 return (token_obj.user, token_obj) def authenticate_header(self, request): """ Return a string to be used as the value of the `WWW-Authenticate` header in a `401 Unauthenticated` response, or `None` if the authentication scheme should return `403 Permission Denied` responses. """ pass
路径:api\utils\permission.py
from rest_framework.permissions import BasePermission class SVIP_Permission(BasePermission): def has_permission(self, request, view): """ Return `True` if permission is granted, `False` otherwise. """ if request.user.user_type == 3: # 用户类型是3,才有权限 return True return False def has_object_permission(self, request, view, obj): """ Return `True` if permission is granted, `False` otherwise. """ return True class VIP_Permission(BasePermission): message = "您没有访问权限,请购买VIP后再来" def has_permission(self, request, view): """ Return `True` if permission is granted, `False` otherwise. """ if request.user.user_type >= 2: # 比2大的都有权限,SVIP是3 也满足条件 return True return False def has_object_permission(self, request, view, obj): """ Return `True` if permission is granted, `False` otherwise. """ return True class Common_Permission(BasePermission): def has_permission(self, request, view): """ Return `True` if permission is granted, `False` otherwise. """ if request.user.user_type >= 1: # 比1大的都有权限 return True return False def has_object_permission(self, request, view, obj): """ Return `True` if permission is granted, `False` otherwise. """ return True
路径:api\utils\permission.py
from rest_framework.throttling import BaseThrottle,SimpleRateThrottle import time VISIT_RECORD = {} class Throttles_by_myself(BaseThrottle): ''' 节流控制类,匿名访问,基于IP进行控制 自己写规则,完全自己写的那种 ''' def __init__(self): self.history = None def allow_request(self, request, view): # 继承BaseThrottle,就必须重写这个方法 # 1. 获取用户IP # get_ident是基类给我们提供的方法,用以获取IP remote_addr = self.get_ident(request) ctime = time.time() if remote_addr not in VISIT_RECORD: VISIT_RECORD[remote_addr] = [ctime, ] return True history = VISIT_RECORD.get(remote_addr) self.history = history while history and history[-1] < ctime - 60: # 60秒 之外的值,踢出列表 history.pop() if len(history) < 3: history.insert(0, ctime) # return True # 表示可以继续访问 # return False # 表示访问频率太高,被限制 return True def wait(self): # 还需要等多少秒才能访问 ctime = time.time() return 60 - (ctime - self.history[-1]) class VisitThrottle(SimpleRateThrottle): # 基于SimpleRateThrottle类的匿名访问节流 # 自定义 scope 和 ident 值,写在settings里边 # soup:节流控制类的 代号 # ident,节流控制频率 3/m 可选单位:s m h d ... scope = "Luffy" def get_cache_key(self, request, view): # 匿名用户以IP为key,写入缓存 return self.get_ident(request) class UserThrottle(SimpleRateThrottle): # 基于SimpleRateThrottle类的登陆用户访问节流 scope = "LuffyUser" def get_cache_key(self, request, view): # 登陆用户以username为key,写入缓存 return request.user.username
路径:api\views.py
from django.shortcuts import render from rest_framework.views import APIView from test_restful import models from django.http import JsonResponse from rest_framework.request import Request from rest_framework import exceptions from rest_framework.authentication import BasicAuthentication from rest_framework.permissions import BasePermission from test_restful.utils import permission def md5(user): import hashlib import time ctime = str(time.time()) m = hashlib.md5(bytes(user,encoding='utf-8')) m.update(bytes(ctime,encoding='utf-8')) return m.hexdigest() class Get_token(APIView): ''' 小练习:自己写的账号密码认证,通过后获取token(每次登陆都更新token) http://127.0.0.1:8000/api/129/get_token/ method:POST body里加入 formdata username - hua password - 123 ''' authentication_classes = [] #这个不做token认证,只核对账户密码 premission_classes = [BasePermission,] # 默认全通过 ret = {'code':1000,'msg':''} def post(self,request,*args,**kwargs): ret = {'code': 1000, 'msg': '','token':''} try: usr = request._request.POST.get('username') pwd = request._request.POST.get('password') obj = models.UserInfo.objects.filter(username=usr,password=pwd).first() if not obj: ret['code'] = 1001 ret['msg'] = '用户名或密码错误' # 为登录用户创建token token = md5(usr) models.UserToken.objects.update_or_create(user=obj,defaults={'token':token}) ret['msg'] = '成功获取token!每次请求都会更新' ret['token'] = token except Exception as e: pass return JsonResponse(ret) class Authtication(object): ''' 构建一个最基础的用户认证类,没有实际意义,仅用于熟悉它的使用方法 ''' def authenticate(self,request): token = request._request.GET.get('token') token_obj = models.UserToken.objects.filter(token=token).first() if not token_obj: raise exceptions.AuthenticationFailed('哎呀,没通过') # 返回元组,用于rest_freamwork 的后续操作 # token_obj.user是用户类的实例 token_obj是token类的实例 return (token_obj.user,token_obj) def authenticate_header(self, request): """ Return a string to be used as the value of the `WWW-Authenticate` header in a `401 Unauthenticated` response, or `None` if the authentication scheme should return `403 Permission Denied` responses. """ pass class Order(APIView): ''' 局部使用 类认证 http://127.0.0.1:8000/api/129/order 假想订单,加了认证就获取不到结果 http://127.0.0.1:8000/api/129/order?token=ca7532bb9c112709a0f1a08203bbf069 加了认证,必须带着token才有正确返回值 ''' authentication_classes = [Authtication,] def get(self,request,*args,**kwargs): ret = {'code': 1000, 'msg': ''} try: ret['data'] = '订单列表' except Exception as e: pass return JsonResponse(ret) class By_utils_auth(APIView): # http://127.0.0.1:8000/api/129/utils_auth # 认证类在settings里边指定,全局有效。不想认证的话加一句 authentication_classes = [] 就行 def get(self,request,*args,**kwargs): ret = {'code': 1000, 'msg': ''} try: ret['data'] = '以后都使用utils,在settings里边配置全局的用户认证' except Exception as e: pass return JsonResponse(ret) #######################权限管理############# class Common_view(APIView): ''' 普通用户及以上 有权查看 http://127.0.0.1:8000/api/129/common_view/?token=9b30493482a649f11d81a93511c86bbb ''' permission_classes = [permission.Common_Permission] def post(self,request,*args,**kwargs): ret = {'code': 1000, 'msg': ''} try: ret['msg'] = '普通用户视图' ret['request'] = str(request) ret['request.user'] = str(request.user) ret['request.auth'] = str(request.auth) ret['用户类型'] = str(request.user.user_type) print('*******',request,'*******') print('*******','request.user:',request.user,'*******') print('*******','用户类型:',request.user.user_type,'*******') print('*******', 'request.auth:', request.user, '*******') except exceptions.APIException as e: pass return JsonResponse(ret) class VIP_view(APIView): ''' 普通用户及以上 有权查看 http://127.0.0.1:8000/api/129/vip_view/?token=9b30493482a649f11d81a93511c86bbb ''' permission_classes = [permission.VIP_Permission] def post(self,request,*args,**kwargs): ret = {'code': 1000, 'msg': ''} try: ret['msg'] = 'VIP级以上用户视图' except exceptions.APIException as e: pass return JsonResponse(ret) class SVIP_view(APIView): ''' SVIP 有权查看 http://127.0.0.1:8000/api/129/svip_view/?token=9b30493482a649f11d81a93511c86bbb ''' permission_classes = [permission.SVIP_Permission] def post(self,request,*args,**kwargs): ret = {'code': 1000, 'msg': ''} try: ret['msg'] = 'SVIP级以上用户视图' except exceptions.APIException as e: pass return JsonResponse(ret) #######################频率管理/节流控制############# class Throttle_view1(APIView): ''' 依靠自己实现的Throttles_by_myself类,做匿名用户节流 http://127.0.0.1:8000/api/129/throttle_view1 ''' from test_restful.utils.throttle import Throttles_by_myself authentication_classes = [] permission_classes = [permission.BasePermission] throttle_classes = [Throttles_by_myself] def get(self, request, *args, **kwargs): ret = {'code': 1000, 'msg': ''} try: ret['msg'] = '60秒内限制匿名访问3次' except exceptions.APIException as e: pass return JsonResponse(ret) class Throttle_view2(APIView): ''' http://127.0.0.1:8000/api/129/throttle_view2 依靠VisitThrottle(SimpleRateThrottle)类,做匿名用户节流 自定义 scope 和 ident 值,写在settings里边 soup:节流控制类的 代号 ident,节流控制频率 3/m 可选单位:s m h d ... ''' from test_restful.utils.throttle import VisitThrottle authentication_classes = [] permission_classes = [permission.BasePermission] throttle_classes = [VisitThrottle] def get(self, request, *args, **kwargs): ret = {'code': 1000, 'msg': ''} try: ret['msg'] = '一分钟内限制匿名访问3次' except exceptions.APIException as e: pass return JsonResponse(ret) class Throttle_view3(APIView): ''' http://127.0.0.1:8000/api/129/throttle_view3?token=ca7532bb9c112709a0f1a08203bbf069 依靠VisitThrottle(SimpleRateThrottle)类,做匿名用户节流 自定义 scope 和 ident 值,写在settings里边 soup:节流控制类的 代号 ident,节流控制频率 3/m 可选单位:s m h d ... ''' from test_restful.utils.throttle import UserThrottle permission_classes = [permission.BasePermission] throttle_classes = [UserThrottle] def get(self, request, *args, **kwargs): ret = {'code': 1000, 'msg': ''} try: ret['msg'] = '登录用户,一分钟内限制访问10次' except exceptions.APIException as e: pass return JsonResponse(ret)