返回顶部

DRF之认证

一. DRF认证

局部认证组件

  我们知道,我们不管路由怎么写的,对应的视图类怎么写的,都会走到dispatch方法,进行分发,

  在咱们看的APIView类中的dispatch方法的源码中,有个self.initial(request, *args, **kwargs),那么认证、权限、频率这三个默认组件都在这个方法里面了,如果我们自己没有做这三个组件的配置,那么会使用源码中默认的一些配置。进源码去看看你就会看到下面三个东西:

# Ensure that the incoming request is permitted
#实现认证
self.perform_authentication(request)
#权限判断
self.check_permissions(request)
#控制访问频率
elf.check_throttles(request)

 

 

 

models:

  首先我们需要创建一个表,用户表,里面放一个token字段,其实一般我都是放到两个表里面,和用户表是一个一对一关系的表,看代码:

from django.db import models

# Create your models here.

class UserInfo(models.Model):

    username = models.CharField(verbose_name='用户名', max_length=32)
    password = models.CharField(verbose_name='密码', max_length=32)



class UserToken(models.Model):
    user = models.OneToOneField('UserInfo', on_delete=models.CASCADE)
    token = models.CharField(verbose_name='token值', max_length=64)

做了一层路由分发:

path('auth/', include('authDemo.urls'))

urls:

from django.urls import path

from authDemo.views import DemoView,AuthDemo,TestView

urlpatterns = [

    path('', DemoView.as_view()),
    path('login', AuthDemo.as_view()),
    path('test', TestView.as_view())

]

自定义认证类:

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

from authDemo import models

class MyAuth(BaseAuthentication):

    def authenticate(self, request):
        request_token = request.query_params.get("token", None)
        if not request_token:
            raise AuthenticationFailed({"code": 1001, "error": "缺少token"})
        token_obj = models.UserToken.objects.filter(token=request_token).first()
        if not token_obj:
            raise AuthenticationFailed({"code": 1001, "error": "无效的token"})
        return token_obj.user, token_obj.token

views:

from uuid import uuid4
from django.shortcuts import render
from django.http import JsonResponse

from rest_framework.views import APIView
from rest_framework.response import Response

from authDemo import models
from utiles.auth import MyAuth
# Create your views here.

class DemoView(APIView):

    def get(self, request):

        return Response('认证DEMO')


class AuthDemo(APIView):

    def post(self, request, *args, **kwargs):
        ret = {'code': 1000, 'msg': None}
        try:
            username = request.data.get('user')
            password = request.data.get('pwd')
            user_obj = models.UserInfo.objects.filter(username=username, password=password).first()
            if not user_obj:
                ret['code'] = 2001
                ret['msg'] = '用户名或密码错误!'
                return JsonResponse(ret, safe=False, json_dumps_params={'ensure_ascii': False})
            uuid = str(uuid4())
            models.UserToken.objects.update_or_create(user=user_obj, defaults={'token': uuid})
            ret['token'] = uuid
        except Exception as e:
            ret['code'] = 2000
            ret['msg'] = '请求异常'
        return JsonResponse(ret, safe=False, json_dumps_params={'ensure_ascii': False})


class TestView(APIView):

    authentication_classes = [MyAuth,]

    def get(self, request):
        print(request.user)
        print(request.auth)
        # user_id = request.user.id

        return Response("认证测试")

其实最最要的步骤就是:

1.自定义认证类,继承了 BaseAuthentication  之后,还需要实现 authenticate(self, request): 这个方法,并且返回值一定的是一个元组 

#源码中会发现,这个方法会有两个返回值,并且这两个返回值封装到了新的request对象中了,request.user-->用户名 和 request.auth-->token值,这两个值作为认证结束后的返回结果

2.视图中应用  authentication_classes = [MyAuth,]  这就是局部应用上了我们自己写的认证类。

 

 

全局视图认证组件

配置settings文件:


REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES": ["utils.auth.MyAuth"]  #里面是路径字符串
}

如果配置了全局认证类后,想在某个试图中不进行认证的话,可以  authentication_classes = [  ]传一个空列表

 

posted @ 2020-10-14 20:49  muguangrui  阅读(83)  评论(0编辑  收藏  举报