认证

认证组件

认证有什么用:

  一些接口,想限制登录的后才能访问,没登录不能访问

  做登录认证,限制如果没登录,不允许访问该接口

 

drf中认证类如何使用:

  1、写一个类,继承BaseAuthentication

  2、类中重写:authenticate方法

  3、在authenticate完成登录认证,如果登录了,返回两个值,第一个值是user_token.user,第二个是token,如果能拿的出就是登录了,拿不出就是未登录,抛异常

  4、在视图类中配置使用

      class BookView(ViewSet):

        authentication_classes = [LoginAuth]

 

认证小结:

  1、认证类的使用:

    配置在视图类上:局部使用

    配置文件中配置:全局使用——所有接口必须登录后才能使用(值得注意的是,这里的全局使用也包含了登录本身,所以要对登录进行局部禁用)

全局使用(配置文件中):
REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': [
            'app01.auth.LoginAuth'
            ],
        }

局部禁用:

class UserView(ViewSet):
        authentication_classes = []

2、写的认证类:要重写authenticate方法,必须返回两个参数:

  当前登录用户返回:第一个参数是user_token.user,第二个参数是用户的 token

  在视图类中显示的是:request.user(认证类的第一个参数),request.auth认证类返回的第二个参数

3、如果认证失败就抛异常

  AuthenticationFailed,会被def捕获处理,不会报错到前端

4、前端传入的token,如何取:

  后端定的,我们项目是从请求地址中取,还可以从请求头或者请求体中取

5、update_or_create方法:

   update_or_create(self, defaults=None, **kwargs)

    如果 **kwargs有值,defaults就是更新

    如果**kwargs没有值,defaults就是新增

 登录认证例子:

auth:

from.models import UserToken

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed

class Loginauth(BaseAuthentication):
    def authenticate(self, request):
        #从请求地址中输入token
        token = request.query_params.get('token')
        #如果当前token和数据库中的token匹配
        res = UserToken.objects.filter(token=token).first()
        if res:
            return res.user,token
        else:
            raise AuthenticationFailed('还未登录')

views:

#登录功能
from rest_framework.viewsets import ViewSet
from .models import User,UserToken
from rest_framework.decorators import action
import uuid
class LoginView(ViewSet):
    @action(methods=['POST'],detail=False)
    def logini(self,request):
        name = request.data.get('name')
        password = request.data.get('password')
        user = User.objects.filter(name=name,password=password).first()
        if user:
            #第一种方法
            # #先生成token
            token =str(uuid.uuid4())
            # #查找是否有token,有就修改,没有添加
            # token_find = UserToken.objects.filter(user=user).first()
            # if token_find:
            #     token_find.token = token
            #     token_find.save()
            # else:
            #     UserToken.objects.create(user=user,token=token)
            #第二种方法
            UserToken.objects.update_or_create(defaults={'token':token},user=user) #如果用户存在就修改token,如果不存在就加入
            return Response({'code':200,'msg':'登录成功','token':token,'name':user.name})
        else:
            return Response({'code':100,'msg':'用户名或密码错误'})

from .auth import Loginauth
class BookView(ViewSet):
    authentication_classes = [Loginauth]
    def list(self,request):
        print(request.user)  #User object (1)
        print(request.user.name)  # 当前登录用户  #qx
        print(request.auth)  # 用得少   72e37d8c-1088-4688-8f23-8459ee191615
        return Response("你好:%s,你看到了好多书啊" % request.user.name)

路由:

 

认证类取数据

请求地址取token:token = request.query_params.get('token')

请求头取token:

token = request.META.get('HTTP_TOKEN')

请求体取token:token = request.data.get('token')

权限组件

系统中有普通用户,超级用户,超级管理员,分权限访问,有权限可以进这个接口,没权限就不能访问

使用步骤:

  1、写一个类,继承BasePermission

  2、重写has_permission

  3、在方法中校验用户是否权限,如果有就返回True,如果没有,就返回False

      因为执行在认证之后,所以从request.user中取出当前用户,判断权限

  4、在视图类中局部使用,在settings中全局使用,局部可以禁用

    class PublishView(ViewSet):
      permission_classes = [UserPermission]  (局部使用)

   全局使用:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'app01.auth.LoginAuth'
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'app01.permissions.UserPermission',
    ],
}

 

permissions.py
from rest_framework.permissions import BasePermission


class Userpermission(BasePermission):
    # 重写源码中的has_permission
    def has_permission(self, request, view):
        # 要在登录认证后执行,才能取到request.user.user_type
 if request.user.user_type == 3: return True else: self.message = '您的用户等级为%s,无权限访问' % (request.user.get_user_type_display()) return False

 

 认证在权限后面才能取到上述值

视图类

 

django项目国际化

# 配置文件中--->以后所有英文都会转成中文
INSTALLED_APPS = [
    'rest_framework'
]

LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False

 

 频率组件

from rest_framework.throttling import SimpleRateThrottle

控制一个接口,访问频次,例如一分钟访问几次

对接口进行访问次数限制

使用步骤:

  1、写一个类,继承一个SimpleRateThrottle

  2、重写get_cache_key,返回什么就以什么做限制,IP限制,用户id限制

  3、写一个类属性 例如scope = 'drf_day08'

  4、配置文件中配置    

      'DEFAULT_THROTTLE_RATES': {
      'drf_day08': '3/m',     # 一分钟访问三次 5/s,m,h,d
      },

   5、局部使用,全局使用,局部禁用

      class PublishView(ViewSet):
        throttle_classes = [IPRateThrottle]

  6、全局使用

    'DEFAULT_THROTTLE_CLASSES': ['app01.throttling.IPRateThrottle'],  (这里的名字根据throttling.py的命名来写

 

 

 hrottling.py

id限制

 ip限制

 view.py

 排序

只有五个接口中的查询所有,才涉及到排序

查询所有用户

使用步骤

1、必须写在继承:GenericAPIView 类的视图类中才行

2、配置类属性:

  filter_backends = [OrderingFilter]

  ordering_fields=['id','user_type']   #可以排序的字段

3、使用

http://127.0.0.1:8000/user/?ordering=user_type #用户类型升序排
http://127.0.0.1:8000/user/?ordering=-user_type #用户类型降序排
http://127.0.0.1:8000/user/?ordering=user_type,-id#先按用户类型升序排,如果用户类型一样,再按id降序排

 

 

 

 

频率源码

 

 

 

 

 

 

 

 

 

  

posted @ 2023-09-06 16:41  别管鱼油我了  阅读(19)  评论(0编辑  收藏  举报