• Django REST framework


    Django REST framework 权限和限制

    (你能干什么)

    与身份验证和限制一起,权限确定是应该授予还是拒绝访问请求。

    在允许任何其他代码继续之前,权限检查始终在视图的最开始运行。权限检查通常使用 request.userrequest.auth 属性中的身份验证信息来确定是否应允许传入请求。

    权限用于授予或拒绝不同类别的用户访问API的不同部分。

    最简单的权限类型是允许访问任何经过身份验证的用户,并拒绝访问任何未经身份验证的用户。这对应IsAuthenticated于REST框架中的类。

    稍微不那么严格的权限样式是允许对经过身份验证的用户进行完全访问,但允许对未经身份验证的用户进行只读访问。这对应IsAuthenticatedOrReadOnly于REST框架中的类。

    设置权限的方法

    1. 可以使用该DEFAULT_PERMISSION_CLASSES设置全局设置默认权限策略。例如:

       REST_FRAMEWORK = {
           'DEFAULT_PERMISSION_CLASSES': (
               	'rest_framework.permissions.IsAuthenticated',
           )
       }
      

    如果未指定,则此设置默认允许不受限制的访问:

    	'DEFAULT_PERMISSION_CLASSES': (
    	   'rest_framework.permissions.AllowAny',
    	)
    
    1. 您还可以使用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)
      
    2. 或者,使用@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)
      

    注意 :当您通过类属性或装饰器设置新的权限类时,您告诉视图忽略settings.py文件中的默认列表集。

    如果它们继承自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",
        }
    }
  • 相关阅读:
    DataWhale《零基础入门数据挖掘》第二次打卡
    成功解决socket.timeout: The read operation timed out问题
    Pandas函数set_option()学习笔记
    [打卡]动手学深度学习第四次打卡
    [打卡]动手学深度学习第三次打卡
    [深度学习]动手学深度学习笔记-15
    [深度学习]动手学深度学习笔记-14
    [深度学习]动手学深度学习笔记-13
    [深度学习]动手学深度学习笔记-12
    jsp标准标签库——jstl
  • 原文地址:https://www.cnblogs.com/konghui/p/10351911.html
Copyright © 2020-2023  润新知