首页 > 其他分享 >【八】DRF之认证频率权限

【八】DRF之认证频率权限

时间:2023-07-31 12:24:55浏览次数:30  
标签:DEFAULT self request rest 认证 framework user 权限 DRF

【一】准别数据

  • 为了方便接下来的学习,我们创建一个新的子应用 opt
python manage.py startapp opt
  • 因为接下来的功能中需要使用到登陆功能
    • 所以我们使用django内置admin站点并创建一个管理员.
python3 manage.py makemigrations
python3 manage.py migrate
python3 manage.py createsuperuser

  • 创建管理员以后,访问admin站点,先修改站点的语言配置
  • settings.py
LANGUAGE_CODE = 'zh-hans'  # 中文

TIME_ZONE = 'Asia/Shanghai' # 时区是亚洲上海

USE_I18N = True # 国际化

USE_L10N = True # 本地化

USE_TZ = True # 数据库是否使用TIME_ZONE,True表示使用上海的时区,False表示不使用,使用UTC时间,然后转成上海,会差8个小时

  • 访问admin 站点效果:

【二】认证(Authentication)

【1】自定义认证方案

(1)编写models

# models.py
class User(models.Model):
    username=models.CharField(max_length=32)
    password=models.CharField(max_length=32)
    user_type=models.IntegerField(choices=((1,'超级用户'),(2,'普通用户'),(3,'二笔用户')))

class UserToken(models.Model):
    user=models.OneToOneField(to='User')
    token=models.CharField(max_length=64)

(2)新建认证类

from rest_framework.authentication import BaseAuthentication
class TokenAuth():
    def authenticate(self, request):
        token = request.GET.get('token')
        token_obj = models.UserToken.objects.filter(token=token).first()
        if token_obj:
            return
        else:
            raise AuthenticationFailed('认证失败')
    def authenticate_header(self,request):
        pass

(3)编写视图

def get_random(name):
    import hashlib
    import time
    md=hashlib.md5()
    md.update(bytes(str(time.time()),encoding='utf-8'))
    md.update(bytes(name,encoding='utf-8'))
    return md.hexdigest()
class Login(APIView):
    def post(self,reuquest):
        back_msg={'status':1001,'msg':None}
        try:
            name=reuquest.data.get('name')
            pwd=reuquest.data.get('pwd')
            user=models.User.objects.filter(username=name,password=pwd).first()
            if user:
                token=get_random(name)
                models.UserToken.objects.update_or_create(user=user,defaults={'token':token})
                back_msg['status']='1000'
                back_msg['msg']='登录成功'
                back_msg['token']=token
            else:
                back_msg['msg'] = '用户名或密码错误'
        except Exception as e:
            back_msg['msg']=str(e)
        return Response(back_msg)



class Course(APIView):
    authentication_classes = [TokenAuth, ]

    def get(self, request):
        return HttpResponse('get')

    def post(self, request):
        return HttpResponse('post')

(4)全局使用

REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",]
}

(5)局部使用

#局部使用,只需要在视图类里加入:
authentication_classes = [TokenAuth, ]

【2】内置认证方案(需要配合权限使用)

  • 可以在配置文件中配置全局默认的认证方案
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',  # session认证
        'rest_framework.authentication.BasicAuthentication',   # 基本认证
    )
}
  • 也可以在每个视图中通过设置authentication_classess属性来设置
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.views import APIView

class ExampleView(APIView):
    # 类属性
    authentication_classes = [SessionAuthentication, BasicAuthentication]
    ...
  • 认证失败会有两种可能的返回值:

    • 401 Unauthorized 未认证

    • 403 Permission Denied 权限被禁止

【三】权限(Permissions)

  • 权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。

    • 在执行视图的dispatch()方法前,会先进行视图访问权限的判断

    • 在通过get_object()获取具体对象时,会进行模型对象访问权限的判断

【1】自定义权限

(1)编写权限类

# 限制只有超级用户能访问
from rest_framework.permissions import BasePermission
class UserPermission(BasePermission):
    message = '不是超级用户,查看不了'
    def has_permission(self, request, view):
        # user_type = request.user.get_user_type_display()
        # if user_type == '超级用户':
        # 权限在认证之后,所以能取到user
        user_type = request.user.user_type
        print(user_type)
        if user_type == 1:
            return True
        else:
            return False

(2)全局使用

REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",],
    "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",]
}

(3)局部使用

# 局部使用只需要在视图类里加入:
permission_classes = [UserPermission,]

(4)说明

  • 如需自定义权限

    • 需继承rest_framework.permissions.BasePermission父类,并实现以下两个任何一个方法或全部
  • .has_permission(self, request, view)

    • 是否可以访问视图, view表示当前视图对象
  • .has_object_permission(self, request, view, obj)

    • 是否可以访问数据对象, view表示当前视图, obj为数据对象

【2】内置权限

(1)内置权限类

from rest_framework.permissions import 
# AllowAny,IsAuthenticated,IsAdminUser,IsAuthenticatedOrReadOnly
AllowAny 
# 允许所有用户

IsAuthenticated 
# 仅通过认证的用户

IsAdminUser 
# 仅管理员用户

IsAuthenticatedOrReadOnly 
# 已经登陆认证的用户可以对数据进行增删改操作,没有登陆认证的只能查看数据。

(2)全局使用

  • 可以在配置文件中全局设置默认的权限管理类
REST_FRAMEWORK = {
    ....
    
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    )
}
  • 如果未指明,则采用如下默认配置
'DEFAULT_PERMISSION_CLASSES': (
   'rest_framework.permissions.AllowAny',
)

(3)局部使用

  • 也可以在具体的视图中通过permission_classes属性来设置
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView

class ExampleView(APIView):
    permission_classes = (IsAuthenticated,)
    ...

(4)实际操作

  • 创建超级用户,登陆到admin,创建普通用户(注意设置职员状态,也就是能登陆)
  • 全局配置IsAuthenticated
  • setting.py
'DEFAULT_PERMISSION_CLASSES': (
    'rest_framework.permissions.IsAuthenticated',
)
  • urls.py
path('test/', views.TestView.as_view()),
  • views.py
class TestView(APIView):
    def get(self,request):
        return Response({'msg':'个人中心'})
  • 登陆到admin后台后,直接访问可以,如果没登陆,不能访问
  • 注意:

    • 如果全局配置了

      • rest_framework.permissions.IsAdminUser
    • 就只有管理员能访问,普通用户访问不了

【三】限流Throttling

  • 可以对接口访问的频次进行限制,以减轻服务器压力。
    • 一般用于付费购买次数,投票等场景使用.

【1】自定义频率类

(1)编写频率类

# 自定义的逻辑

#(1)取出访问者ip

#(2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走

#(3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,

#(4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过

#(5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
class MyThrottles():
    VISIT_RECORD = {}
    def __init__(self):
        self.history=None
    def allow_request(self,request, view):
        #(1)取出访问者ip
        # print(request.META)
        ip=request.META.get('REMOTE_ADDR')
        import time
        ctime=time.time()
        # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问
        if ip not in self.VISIT_RECORD:
            self.VISIT_RECORD[ip]=[ctime,]
            return True
        self.history=self.VISIT_RECORD.get(ip)
        # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
        while self.history and ctime-self.history[-1]>60:
            self.history.pop()
        # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
        # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
        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])

(2)全局使用

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES':['app01.utils.MyThrottles',],
}

(3)局部使用

#在视图类里使用
throttle_classes = [MyThrottles,]

【2】内置频率类

(1)根据用户ip限制

  • 写一个类,继承自SimpleRateThrottle,(根据ip限制)
from rest_framework.throttling import SimpleRateThrottle
class VisitThrottle(SimpleRateThrottle):
    scope = 'luffy'
    def get_cache_key(self, request, view):
        return self.get_ident(request)
  • 在setting里配置:(一分钟访问三次)
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_RATES':{
        'luffy':'3/m'  # key要跟类中的scop对应
    }
}
  • 可以全局使用,局部使用
  • 了解:错误信息中文显示
class Course(APIView):
    authentication_classes = [TokenAuth, ]
    permission_classes = [UserPermission, ]
    throttle_classes = [MyThrottles,]

    def get(self, request):
        return HttpResponse('get')

    def post(self, request):
        return HttpResponse('post')
    def throttled(self, request, wait):
        from rest_framework.exceptions import Throttled
        class MyThrottled(Throttled):
            default_detail = '傻逼啊'
            extra_detail_singular = '还有 {wait} second.'
            extra_detail_plural = '出了 {wait} seconds.'
        raise MyThrottled(wait)

(2)限制匿名用户每分钟访问3次

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.AnonRateThrottle',
    ),
    'DEFAULT_THROTTLE_RATES': {
        'anon': '3/m',
    }
}
# 使用 `second`, `minute`, `hour` 或`day`来指明周期。
# 可以全局使用,局部使用

(3)限制登陆用户每分钟访问10次

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.UserRateThrottle'
    ),
    'DEFAULT_THROTTLE_RATES': {
        'user': '10/m'
    }
}
# 可以全局使用,局部使用

(4)其他

1) AnonRateThrottle

  • 限制所有匿名未认证用户,使用IP区分用户。
  • 使用DEFAULT_THROTTLE_RATES['anon'] 来设置频次

2)UserRateThrottle

  • 限制认证用户,使用User id 来区分。
  • 使用DEFAULT_THROTTLE_RATES['user'] 来设置频次

3)ScopedRateThrottle

  • 限制用户对于每个视图的访问频次,使用ip或user id。
  • 例如:
class ContactListView(APIView):
    throttle_scope = 'contacts'
    ...

class ContactDetailView(APIView):
    throttle_scope = 'contacts'
    ...

class UploadView(APIView):
    throttle_scope = 'uploads'
    ...
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.ScopedRateThrottle',
    ),
    'DEFAULT_THROTTLE_RATES': {
        'contacts': '1000/day',
        'uploads': '20/day'
    }
}

【3】实例

  • 全局配置中设置访问频率
'DEFAULT_THROTTLE_RATES': {
    'anon': '3/minute',
    'user': '10/minute'
}
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.generics import RetrieveAPIView
from rest_framework.throttling import UserRateThrottle

class StudentAPIView(RetrieveAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
    authentication_classes = [SessionAuthentication]
    permission_classes = [IsAuthenticated]
    throttle_classes = (UserRateThrottle,)

标签:DEFAULT,self,request,rest,认证,framework,user,权限,DRF
From: https://www.cnblogs.com/dream-ze/p/17593119.html

相关文章

  • 【七】DRF之路由组件
    【一】路由Routers对于视图集ViewSet我们除了可以自己手动指明请求方式与动作action之间的对应关系外还可以使用Routers来帮助我们快速实现路由信息。RESTframework提供了两个routerSimpleRouterDefaultRouter【二】使用方法【1】创建router对象,并注册视图集......
  • 【十】DRF之接口文档相关
    【一】自动生成接口文档RESTframework可以自动帮助我们生成接口文档。接口文档以网页的方式呈现。自动接口文档能生成的是继承自APIView及其子类的视图。【二】安装依赖RESTframewrok生成接口文档需要coreapi库的支持。pipinstallcoreapi【三】设置接口文档访问路......
  • 【九】DRF之过滤排序异常
    【一】过滤(Filtering)对于列表数据可能需要根据字段进行过滤我们可以通过添加django-fitlter扩展来增强支持。pipinstalldjango-filter在配置文件中增加过滤后端的设置:INSTALLED_APPS=[...'django_filters',#需要注册应用,]REST_FRAMEWORK={......
  • 【十一】DRF之JWT认证
    【一】JWT认证在用户注册或登录后,我们想记录用户的登录状态,或者为用户创建身份认证的凭证。我们不再使用Session认证机制,而使用JsonWebToken(本质就是token)认证机制。Jsonwebtoken(JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC7519)该to......
  • 【十二】DRF之RBAC控制
    【一】什么是RBAC【1】概念RBAC是基于角色的访问控制(Role-BasedAccessControl)在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计......
  • 主流的权限模型
    主要有两种: ACL模型:访问控制列表RBAC模型:基于角色的访问控制; 1.ACL模型:访问控制列表AccessControlList,ACL是最早也是最基本的访问控制机制。它是一种基于对象的控制模型,在其他模型中也使用了ACL。为了解决一一配置相同权限用户的问题,后来也采用了用户组的方式。原理:每......
  • 第十三章 Linux帐号管理与ACL权限设定
    第十三章Linux帐号管理与ACL权限设定13.1Linux的帐号与群组13.1.1使用者标识符:UID与GID每个登入的使用者至少都会取得两个ID,一个是使用者ID(UserID,简称UID),一个是群组ID(GroupID,简称GID)。那么文件如何判断他的拥有者与群组呢?其实就是利用UID与GID啦!13.1.2使用者帐号......
  • 捷报:斩获32项认证,6大奖项!
    7月25日,由中国信息通信研究院(简称中国信通院)、中国通信标准化协会主办的“2023可信云大会”在京召开。天翼云出席央国企高质量用云创新赋能计划暨《央国企用云白皮书》研究启动仪式、一云多芯应用创新生态社区成立仪式、智算服务提升计划启动仪式暨首批专家聘任仪式、专有云质效验......
  • 02.FreeIPA、FreeRadius双因子认证
    一、安装先决条件Rocky8(2G内存以上,30G硬盘,镜像源修改为阿里云)二、安装FreeIPA修改SeLinux、关闭防火墙、更新系统:timedatectlset-timezoneAsia/Shanghaisetenforce0systemctlstopfirewalld.servicednfupdate安装前准备:设置主机名:hostnamectlset-hostnamef......
  • .Net Core中自定义认证实现
    一、起因 (原文)最近项目中需要对项目同时支持JWT认证,以及自定义的认证校验方式认证。通过对官方文档了解,得到认证实现主要通过继承 IAuthenticationHandler 或 AuthenticationHandler<TOptions>来实现自定义认证的处理。那么接下来实现一个自定义的认证访问。二、......