目录django
与身份验证和限制一块儿,权限肯定是应该授予仍是拒绝访问请求。api
在容许任何其余代码继续以前,权限检查始终在视图的最开始运行。权限检查一般使用 request.user
和 request.auth
属性中的身份验证信息来肯定是否应容许传入请求。app
权限用于授予或拒毫不同类别的用户访问API的不一样部分。框架
最简单的权限类型是容许访问任何通过身份验证的用户,并拒绝访问任何未经身份验证的用户。这对应IsAuthenticated
于REST框架中的类。ide
稍微不那么严格的权限样式是容许对通过身份验证的用户进行彻底访问,但容许对未经身份验证的用户进行只读访问。这对应IsAuthenticatedOrReadOnly
于REST框架中的类。rest
可使用该DEFAULT_PERMISSION_CLASSES
设置全局设置默认权限策略。例如:code
REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ) }
若是未指定,则此设置默认容许不受限制的访问:orm
'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.AllowAny', )
您还可使用APIView
基于类的视图在每一个视图或每一个视图集的基础上设置身份验证策略。对象
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView继承
class ExampleView(APIView):
permission_classes = (IsAuthenticated,)
def get(self, request, format=None): content = { 'status': 'request was permitted' } return Response(content)
或者,使用@api_view
具备基于功能的视图的装饰器。
from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response @api_view(['GET']) @permission_classes((IsAuthenticated, )) def example_view(request, format=None): content = { 'status': 'request was permitted' } return Response(content)
若是它们继承自rest_framework.permissions.BasePermission,则可使用标准Python按位运算符组合权限。例如,IsAuthenticatedOrReadOnly能够写成:
from rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS from rest_framework.response import Response from rest_framework.views import APIView class ReadOnly(BasePermission): def has_permission(self, request, view): return request.method in SAFE_METHODS class ExampleView(APIView): permission_classes = (IsAuthenticated|ReadOnly,) def get(self, request, format=None): content = { 'status': 'request was permitted' } return Response(content)
此案例基于 Django REST framework 认证
"""
本身动手写一个权限组件
"""
from rest_framework.permissions import BasePermission
class MyPermission(BasePermission):
message = '只有VIP才能访问' def has_permission(self, request, view): # 认证类中返回了token_obj.user, request_token # request.auth 等价于request_token if not request.auth: return False # request.user为当前用户对象 if request.user and request.user.type == 1: # 若是是VIP用户 print("requ", request.user, type(request.user)) return True else: return False
class CommentViewSet(ModelViewSet): queryset = models.Comment.objects.all() serializer_class = app01_serializers.CommentSerializer authentication_classes = [MyAuth, ] permission_classes = [MyPermission, ]
# 在settings.py中设置rest framework相关配置项 REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ], "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ] }
import time # from rest_framework.throttling import visit_record = {} class MyThrottle(object): def __init__(self): self.history = None def allow_request(self, request, view): # 拿到当前的请求的ip做为访问记录的 key ip = request.META.get('REMOTE_ADDR') # 拿到当前请求的时间戳 now = time.time() if ip not in visit_record: visit_record[ip] = [] # 把当前请求的访问记录拿出来保存到一个变量中 history = visit_record[ip] self.history = history # 循环访问历史,把超过10秒钟的请求时间去掉 while history and now - history[-1] > 10: history.pop() # 此时 history中只保存了最近10秒钟的访问记录 if len(history) >= 3: return False else: # 判断以前有没有访问记录(第一次来) self.history.insert(0, now) return True def wait(self): """告诉客户端还需等待多久""" now = time.time() return self.history[-1] + 10 - now # history = ['9:56:12', '9:56:10', '9:56:09', '9:56:08'] # '9:56:18' - '9:56:12' # history = ['9:56:19', '9:56:18', '9:56:17', '9:56:08'] # 最后一项到期的时间就是下一次容许请求的时间 # 最后一项到期的时间:now - history[-1] > 10 # 最后一项还剩多少时间过时 # history[-1] + 10 - now
class CommentViewSet(ModelViewSet): queryset = models.Comment.objects.all() serializer_class = app01_serializers.CommentSerializer throttle_classes = [MyThrottle, ]
# 在settings.py中设置rest framework相关配置项 REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ], "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ] "DEFAULT_THROTTLE_CLASSES": ["app01.utils.MyThrottle", ] }
from rest_framework.throttling import SimpleRateThrottle class VisitThrottle(SimpleRateThrottle): scope = "xxx" def get_cache_key(self, request, view): return self.get_ident(request)
# 在settings.py中设置rest framework相关配置项 REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ], # "DEFAULT_PERMISSION_CLASSES": ["app01.utils.MyPermission", ] "DEFAULT_THROTTLE_CLASSES": ["app01.utils.VisitThrottle", ], "DEFAULT_THROTTLE_RATES": { "xxx": "5/m", } }