rest framework 的权限管理

下面是对单个的视图进行的设置的:

请求的时候用postman然后发送信息

我们下面所有的举例都是在用户对Comment这个表的操作

首先先生成一个类似于cookie的字符串 发送给前端浏览器 然后下次它再访问带着这个认证字符串

登陆视图

#登陆视图

class LoginView(APIView):
    def post(self,request):
        ret = {"status":0}
        print(request.data)

        username = request.data.get("username")
        password = request.data.get('password')

        user_obj = models.UserInfo.objects.filter(username = username,password = password).first()  # 校验看传递进来的是否对的
        print(11111)

        if user_obj:
            print(2222222)
            #校验成功 加密并且写入 Token中它的
            token = get_token_code(username)
            models.Token.objects.update_or_create(defaults={'token':token},user = user_obj)  # 有就更新 没有就创建
            ret['token'] = token  #加密的内容存起来
        else:
            ret['status'] = 1
            ret['error'] = "用户名或密码错误"

        return Response(ret)

生成请求的token字符串:

#生成Token函数
def get_token_code(username):
    '''
    根据用户名和时间戳生成用户登陆成功过的随机字符串
    :param username:   字符串格式用户名
    :return:  字符串格式Token
    '''

    import time
    import hashlib
    timestamp = str(time.time())
    m = hashlib.md5(bytes(username,encoding="utf8"))
    m.update(bytes(timestamp,encoding="utf8"))
    return m.hexdigest()

认证:     BaseAuthentication

from rest_framework.authentication import  BaseAuthentication # 认证模块

抛错模块:

from rest_framework.exceptions import AuthenticationFailed   # 模块报错 返回信息

我们可以根据这个来设置 登陆人的信息  只有登陆成功后才能进行提交post之类的操作 

这个时候就用到了我们的权限设置

我们写一个文件来存放登陆的信息设置:

from rest_framework.authentication import  BaseAuthentication # 认证模块

from first import models

from rest_framework.exceptions import AuthenticationFailed   # 模块报错 返回信息
import logging
logger = logging.getLogger(__name__)
class MyAuth(BaseAuthentication):

    def authenticate(self, request):
        print(request.method)
        if request.method in ["POST","PUT","DELETE"]:
            token = request.data.get("token")  #获取你登陆的信息
            token_obj = models.Token.objects.filter(token = token).first()  #去数据库中阿奎那有没有这个数据
            if token_obj:
                return token_obj.user,token
            else:
                raise AuthenticationFailed('无效的token')
        else:
            return None,None

views:

就是把你的认证设置导入进来 然后再用到post get操作的总操作的集合模块对操作设置

from first.utils.auth  import MyAuth  #导入你的 认证信息设置

class CommentViewSet(ModelViewSet):
    queryset = models.Comment.objects.all()
    serializer_class = first_serializers.Commentserializer  #这个是你的对Comment的定义设置的

    authentication_classes =  [MyAuth]   # 让你设置的认证生效

视图级别认证

class CommentViewSet(ModelViewSet):

    queryset = models.Comment.objects.all()
    serializer_class = app01_serializers.CommentSerializer
    authentication_classes = [MyAuth, ]

全局级别认证

# 在settings.py中配置
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ]
}

权限管理:BasePermission  

from rest_framework.permissions import  BasePermission   #导入权限设置的模块

也是设置一个权限管理的模块:

from rest_framework.permissions import  BasePermission   #导入权限设置的模块


class MyPermission(BaseException):
    message = '快滚,没有权限!'

    def has_permission(self,request,view):
        '''
        判断该用户有没有权限
        如果有就返回True
        如果没有就返回False
        '''
        print('我要进行自定义设置了')
        return True

    def has_object_permission(self,request,view,obj):   # 重写父类的方法 名字必须这样

        '''
        obj是你的当前文章的作者对象
        判断当前的评论用户作者是不是你当前的用户
        只有评论的作者才能删除自己的评论
        '''
        if request.method in ['PUT',"DELETE"]:
            if obj.user == request.user:
                # 当前要删除的评论的作者就是当前登陆的用户
                return True
            else:
                return False
        else:
            return True

views:

from first.utils.auth  import MyAuth  #导入你的 认证信息设置
from first.utils.permission import MyPermission  #导入权限管理的模块

class CommentViewSet(ModelViewSet):
    
    queryset = models.Comment.objects.all()
    serializer_class = first_serializers.Commentserializer  #这个是你的对Comment的定义设置的

    authentication_classes =  [MyAuth,]
 
    permission_classes = [MyPermission,]  # 把你权限管理的设置导入进来

这个时候你就要给你的url设置了 就像之前解除的  继承全局的然后并不需要设置很多url  设置一个就可以

ursl:

from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r'comment', views.CommentViewSet)    #这个就是设置你的输入并且查找的视图
urlpatterns += router.urls

限制:

from rest_framework.throttling import  SimpleRateThrottle

定义一个访问次数限制:

自定以的限制:

class VisitThorttle(SimpleRateThrottle):
    scope = "ooo"  #这个名字随便起 是你设置全局的时候的给对应的
    def get_cache_key(self, request, view):
        return self.get_ident(request)  # 求当前访问的IP

其实上面是执行了这个流程:

'''
自定义访问限制类
'''


from rest_framework.throttling import BaseThrottle,SimpleRateThrottle

from rest_framework.throttling import  SimpleRateThrottle

import time

D = {}

class MyThorttle(BaseThrottle):
    def allow_request(self, request, view):
        '''
        返回True就放行 返回False 表示被限制了

        '''
        # 获取当前的ip
        ip = request.META.get("REMOTE_ADDR") # 获取请求的IP
        print('这是自定义希纳是类的allow_request')
        print(ip)

        #获取当前时间
        now = time.time()
        #判断当前ip是否有访问记录
        if ip in D:
            D[ip] = []  #初始化一个空的访问历史列表
        #高端
        history = D[ip]
        while history and now -history[-1] > 30:  #有ip并且当前时间减去储存的最后一个时间
            history.pop()
        if len(history) >= 3:
            return False
        else:
    # 把这一次的访问时间加到访问历史列表的第一位
            D[ip].insert(0,now)
            return True


class VisitThorttle(SimpleRateThrottle):
    scope = "ooo"  #这个名字随便起
    def get_cache_key(self, request, view):
        return self.get_ident(request)  # 求当前访问的IP
真正流程

views:

from first.utils.throttle import VisitThorttle  # 导入自定义访问限制

class CommentViewSet(ModelViewSet):

    queryset = models.Comment.objects.all()
    serializer_class = first_serializers.Commentserializer  #这个是你的对Comment的定义设置的
   throttle_classes = [VisitThorttle,]   #把自定义的访问限制类

全局设置   全局的请求设置是你只要进去就会触发  而我们在views中的设置  只是有针对的对一些视图进行设置

全局设置:

在settings设置;

# rest framework相关的配置项
REST_FRAMEWORK = {
     关于认证的全局配置
     'DEFAULT_AUTHENTICATION_CLASSES': ['app01.utils.auth.MyAuth', ],
     'DEFAULT_PERMISSION_CLASSES': ['app01.utils.permission.MyPermission'],
     #"DEFAULT_THROTTLE_CLASSES": ["app01.utils.throttle.MyThrottle", ],
    "DEFAULT_THROTTLE_RATES": {  # 这个和上面的都可以设置  
            "ooo": "5/m",    # ooo对应你后自定以的设置的scope
            "xxx": '10/m'
        }
}

 

原文地址:https://www.cnblogs.com/zhaoyunlong/p/9416569.html