DRF三大认证

一、认证组件

1.基本使用

​ 关于认证组件,现实生活中我们经常用到该组件,比如逛淘宝在首页浏览商品不用登录,搜商品也不需要登录,游客模式即可。但是一旦涉及到加入购物车、收藏商品需要先登录。这就是典型的登录认证。那么接下来我们一起研究一下认证组件的后端代码实现逻辑吧!首先我们罗列一下整体大逻辑。

  1. 创建一个py文件,里面写认证类、继承BaseAuthentication
  2. 在该文件里的认证类下重写authenticate方法,该方法是逻辑的重点也是难点
  3. 如果认证成功、返回两个值【或返回None】
  4. 如果认证不通过、就直接抛异常AuthenticationFailed
  5. 最后根据具体需求实现全局使用或局部使用的设置

现在有个需求:
查询所有图书不需要登录认证
查询单个图书需要登录认证

当然前提是:
咱得有模型表、序列化器、登录功能,在此基础上实现该功能。
接下来小编会非常详细的通俗易懂的表达来讲解以下吧,具体步骤继续往后看哟。

写视图类

from rest_framework.viewsets import ViewSetMixin  # 导入可以自动生成路由
from rest_framework.generics import ListAPIView, RetrieveAPIView  # 查所有 查单个
from .serializer import BookSerializer  # 序列化器
from .models import Book  # 模型表
from .authenticate import LoginAuth  # 认证类


class BookView(ViewSetMixin, ListAPIView):
    """查询所有接口"""
    queryset = Book.objects.all()
    serializer_class = BookSerializer


class BookDetail(ViewSetMixin, RetrieveAPIView):
    """查询单个数据"""
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # 查询单个需要登录认证,写完认证类之后这里引用即可
    authentication_classes = [LoginAuth]

写认证类

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


class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        # 这里实现认证 如果是登录了往后,如果不是直接抛异常
        # 通过请求中token判断是否登录,放在地址栏
        token = request.query_params.get('token', None)
        if token:  # 前端传入token了, 去表中查 如果能查到表名登录, 返回两个值或None
            user_token = UserToken.objects.filter(token=token).first()
            if user_token:
                return user_token.user, token
            else:
                # 没有登录就抛异常
                raise AuthenticationFailed('token认证失败')
        else:
            raise AuthenticationFailed('没拿到token')

写路由哟

# 第一步 导入模块以及路由类
from django.contrib import admin
from django.urls import path, include
from app01 import views
from rest_framework.routers import SimpleRouter, DefaultRouter

# 第二步 实例化得到对象
router = SimpleRouter()

# 第三步 注册(路径和视图类建立了关系,有几个视图就注册几次)
router.register('books', views.BookView, 'books')  # /api/v1/user/login     post 请求
router.register('books', views.BookDetail, 'books')  # /api/v1/user/login     post 请求

# 第四步 在urlpatterns里添加
urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/', include(router.urls)),

2.局部以及全局使用方法

局部使用

上面步骤的就是局部使用,在某个试图类下按照要求写入认证类即可,这样当前视图类管理的所有的接口都可以使用该认证,全局不受影响

 
class BookDetailView(ViewSetMixin, RetrieveAPIView):
    # 按照这个格式,引入认证类即可
    authentication_classes = [LoginAuth]
             

全局使用

全局所有接口都生效(登录接口不要)
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES':['app01.authenticate.LoginAuth']
	}

局部禁用

如果全局配完之后,局部某个视图需要禁用,那么authentication_classes等于一个空列表既可以实现
具体操作如下
class BookDetailView(ViewSetMixin, RetrieveAPIView):
    authentication_classes = []

二、权限组件

1.基本使用

照样,先大概罗列一下整体步骤

  1. 创建py文件里面写权限类,继承BasePermission
  2. 在权限类重写has_permission方法,该方法实现权限认证,request.user就是当前登录用户
  3. 如果有权限,返回True
  4. 如果没有权限,返回False,定制返回的中文:self.message='中文解释'
  5. 最后根据具体需求实现局部或全局使用的设置

新建py文件,在里面写权限类

from rest_framework.permissions import BasePermission


class CommonPermission(BasePermission):
    def has_permission(self, request, view):
        # 实现权限的控制,如果有权限
        if request.user.user_type == 1:
            return True
        else:
            self.message = '您是【%s】,您没有权限' % request.user.get_user_type_display()
            return False

在视图类引入即可实现局部配置

from .permission import CommonPermission  # 权限类


class BookDetailView(ViewSetMixin, RetrieveAPIView):
    permission_classes = [CommonPermission]

2.局部及全局使用

全局使用

REST_FRAMEWORK = {
	'DEFAULT_PERMISSION_CLASSES': ['app01.permissions.CommonPermission']
}

局部禁用

class BookDetailView(ViewSetMixin, RetrieveAPIView):
    permission_classes = []

三、频率组件

1.基本使用

  1. 新建py文件写一个频率类,继承SimpleRateThrottle
  2. 里面重写get_cache_key方法,返回什么,就以什么做限制----》ip,用户id做限制
  3. 配置一个类属性:scope = 'book_5_m'
  4. 最后根据具体需求实现局部或全局使用的设置

写频率类

from rest_framework.throttling import ScopedRateThrottle


class CommonThrottle(ScopedRateThrottle):
    # scope是类属性 对应的值随便定义
    scope = 'zzz'
    def get_cache_key(self, request, view):
        # 返回什么就以什么做频率限制(可以id也可以是IP)
        # 客户端IP地址从哪里拿
        return request.META.get('REMOTE_ADDR')  # 以ip做限制
        # return request.user.pk  # 以用户id做限制

在视图类

from .throttle import CommonThrottle


class BookDetailView(ViewSetMixin, RetrieveAPIView):
	throttle_classes = [CommonThrottle] 
	
# 在配置文件里需要加这个配置才会实现频率限制
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': ['app01.throttle.CommonThrottle'],
    'DEFAULT_THROTTLE_RATES': {
        'zzz': '5/h',
    },

2.全局及局部使用

全局配置

REST_FRAMEWORK = {
	'DEFAULT_THROTTLE_CLASSES': ['app01.throttling.CommonThrottle']
}

局部禁用

class BookDetailView(ViewSetMixin, RetrieveAPIView):
	throttle_classes = []