12_06、认证,频率,权限

一、登录接口

登录接口编写思路

  -创建表:User表,一对一UserToken表
  -前端传入用户名,密码---》User表中查,如果能查到---》让他登陆成功---》并在UserToken中存一条记录---》返回给前端json格式字符串---》字符串中带一个随机字符串

登录接口表模型

复制代码
class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    user_type = models.IntegerField(choices=((1, '超级管理员'), (2, '普通管理员'), (3, '普通用户')))
    # gender=models.IntegerField(choices=((1,"男"),(2,"女"),(0,"未知"))) # 1:男  2:女 0:未知
    # user对象.get_字段名_display()  快速取出gender数字对应的中文


class UserToken(models.Model):
    user = models.OneToOneField(to=User,on_delete=models.CASCADE)
    token = models.CharField(max_length=32)
复制代码

登录接口视图

复制代码
# class UserView(ViewSetMixin,APIView):
class UserView(ViewSet):
    @action(methods=['POST'], detail=False)
    def login(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        user = User.objects.filter(username=username, password=password).first()
        if user:
            # 登陆成功--》生成一个随机字符串-->存到token表中(如果之前有记录,更新,如果没有新增)
            # uuid生成不重复的串---》理论上不重复
            token = str(uuid.uuid4())  # 伪随机数生成,没有参数,重复概率,比其他的高一些
            UserToken.objects.update_or_create(user=user, defaults={'token': token})  # 如果存在就更新,如果不存在就新增
            return Response({'code': 100, 'msg': '登陆成功', 'token': token})
        else:
            return Response({'code': 101, 'msg': '用户名或密码错误'})
复制代码

登录接口路由

复制代码
from app01 import views
from rest_framework.routers import SimpleRouter
router=SimpleRouter()
router.register('user',views.UserView,'user')

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include(router.urls)),
]
复制代码

二、认证

认证类:用来校验用户是否登录,如果登录了,继续往下走,如果没有登录,直接返回

认证类编写思路

  -第一步:写一个类,继承BaseAuthentication,重写authenticate,在方法中做校验,校验是否登录,返回两个值,没有登录抛异常

复制代码
# 编写认证类
# 全局使用,局部使用

# 步骤:写一个类,继承BaseAuthentication,重写authenticate,在方法中做校验,校验是否登录,返回两个值,没有登录抛异常

class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        # 前端带过来的token,放在哪,是接口(我们)固定的
        token = request.query_params.get('token')
        user_token = UserToken.objects.filter(token=token).first()
        if user_token:  # 登录了
            # 第一个:当前登录用户,第二个:token返回
            return user_token.user, token
        else:
            # 抛出认证失败的异常
            raise AuthenticationFailed('您没有登录')

# 认证类中返回的两个变量,干啥用了
  -返回的第一个,给了request.user,就是当前登录用户
  -返回的第二个,给了request.auth,就是token串
复制代码

  -第二步:全局配置,局部配置

复制代码
# 全局配置:配置文件中
      REST_FRAMEWORK={
      "DEFAULT_AUTHENTICATION_CLASSES":["app01.auth.LoginAuth",]
          }
# 局部配置:在视图类中
      class UserView(ViewSet):
        authentication_classes = [LoginAuth] 
        
# 局部禁用:
       class UserView(ViewSet):
            authentication_classes = [] 
复制代码

三、权限

所有接口必须登陆成功才能访问接口,登陆成功后我们可以赋予不同用户不同的权限

比如,如果用户是普通用户,可以访问所有和单条;如果是普通管理员或者超级用户可以操作所有,除了访问单条还可以访问所有的那个视图类,

这里就需要用到权限类

权限类编写思路
  第一步:写一个类,继承BasePermission,重写has_permission,判断如果有权限,返回True,如果没有权限,返回False

复制代码
# 权限类
from rest_framework.permissions import BasePermission


class UserPermission(BasePermission):
    def has_permission(self, request, view):
        self.message='您是:%s,没有权限'%request.user.get_user_type_display()  # 没有权限的提示信息
        # 如果有权限,返回True,没有权限返回False
        # 权限类,在认证类之后,request.user有了当前登录用户
        user_type = request.user.user_type
        if user_type < 3:  # 只要不是1,2,就没有权限
            return True
        else:
            return False
复制代码

  第二步:局部使用和全局使用

# 局部使用
    class BookDetailView(GenericViewSet, CreateModelMixin, DestroyModelMixin, UpdateModelMixin):
    permission_classes = [UserPermission, ]
    
# 全局使用
      REST_FRAMEWORK={
            "DEFAULT_PERMISSION_CLASSES":["app01.auth.UserPermission",]
        }

四、频率

认证,权限都通过以后,我们可以限制某个接口的访问频率,防止有人恶意攻击网站,一般根据ip或者用户限制

  -第一步:写一个类,继承SimpleRateThrottle,重写类属性:scope,和get_cache_key方法, get_cache_key返回什么,就以什么作限制,scope配置文件中要用

复制代码
# 频率限制类
from rest_framework.throttling import BaseThrottle,SimpleRateThrottle
class IPThrottle(SimpleRateThrottle):
    scope = 'minute_3'  # 随便写
    # 返回什么,就以什么作限制
    def get_cache_key(self, request, view):
        # 限制ip地址---》request.META字典---》请求头中数据
        return request.META.get('REMOTE_ADDR') # 客户端ip
        # return request.user.id # 用户id限制


class UserThrottle(SimpleRateThrottle):
    scope = 'minute_5'  # 随便写
    # 返回什么,就以什么作限制
    def get_cache_key(self, request, view):
        return request.user.id
复制代码

  -第二步:在配置文件中配置

复制代码
# 在配置文件中配置
        'DEFAULT_THROTTLE_RATES': {
        'minute_3': '3/m'  # minute_3是scope的字符串,一分钟访问3次
        'minute_5''5/m'
    }
# 局部使用--》视图类中
  class BookView(GenericViewSet, ListModelMixin, RetrieveModelMixin):
    throttle_classes = [IPThrottle]
# 全局使用--配置文件中
     'DEFAULT_THROTTLE_CLASSES': (  # 全局配置频率类
        'app01.auth.IPThrottle'
    ),
复制代码

 

posted @   三三得九86  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示