drf-router和authenticate认证源码分析

 更新时间:2021年7月11日 00:34  点击:2048

一、路由Routers

在 Rest Framework 中提供了两个 router , 可以帮助我们快速的实现路由的自动生成。

必须是继承 ModelViewSet 的视图类才能自动生成路由

SimpleRouter

使用方法:

urls.py

# 第一步:导入routers模块
from rest_framework import routers

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

# 第三步:注册( register('前缀', viewset视图集, 路由的别名) )
router.register('books', views.BooksViewset)

# 第四步:生成路由加入到原路由中
# 方式一:
urlpatterns = [
    ...
]
urlpatterns += router.urls

# 方式二:
urlpatterns = [
    ...
    url(r'^', include(router.urls))
]


# 形成路由如下
<URLPattern '^books/$' [name='books-list']>
<URLPattern '^books/(?P<pk>[^/.]+)/$' [name='books-detail']>

DefaultRouter

DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。

# 前两条和SimpleRouter一样
<URLPattern '^books/$' [name='books-list']>
<URLPattern '^books/(?P<pk>[^/.]+)/$' [name='books-detail']>

# 效果也和前两条类似,
# 如:http://127.0.0.1:8000/books.json
<URLPattern '^books\.(?P<format>[a-z0-9]+)/?$' [name='books-list']>
# http://127.0.0.1:8000/books/1.json
<URLPattern '^books/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$' [name='books-detail']>

# 多了个根路由http://127.0.0.1:8000/
<URLPattern '^$' [name='api-root']>, <URLPattern '^\.(?P<format>[a-z0-9]+)/?$' [name='api-root']>

action的使用

action是为了给继承自 ModelViewSet 的视图类中自定义的函数也添加路由

例如下面这样:

from rest_framework.viewsets import ModelViewSet
from rest_framework.response import Response
from app01.ser import BooksSerializers
from app01.models import Books


class BooksViewSet(ModelViewSet):
    queryset = Books.objects.all()
    serializer_class = BooksSerializers

    # 这种方法不会自动生成,需要用action配置
    def get_num(self, request, pk):
        book = self.get_queryset()[:int(pk)]
        ser = self.get_serializer(book, many=True)
        return Response(ser.data)

使用示例:

action是一个装饰器,放在被装饰的函数上方,

method:请求方式

detail:是否带pk ——>True 表示路径格式是xxx/<pk>/action方法名/——False 表示路径格式是xxx/action方法名/

from rest_framework.viewsets import ModelViewSet
from rest_framework.response import Response
from rest_framework.decorators import action
from app01.ser import BooksSerializers
from app01.models import Books


class BooksViewSet(ModelViewSet):
    queryset = Books.objects.all()
    serializer_class = BooksSerializers

    @action(methods=['GET', 'POST'], detail=True)
    def get_num(self, request, pk):
        book = self.get_queryset()[:int(pk)]	# 获取前几条数据
        ser = self.get_serializer(book, many=True)
        return Response(ser.data)
    
    
# 生成路由如下
http://127.0.0.1:8000/books/2/get_num/
<URLPattern '^books/(?P<pk>[^/.]+)/get_num/$' [name='books-get-num']>

二、认证

认证的写法

  • 写一个认证类,继承 BaseAuthentication,重写 authenticate, 认证的逻辑写在里面,认证通过,返回两个值,一个值给Request对象的user, 认证失败,抛异常:APIException或者AuthenticationFailed
  • 将认证类添加到需要认证视图类的authentication_classes = [认证类1]
  • 全局使用,还是局部使用

# 全局使用,在setting.py中配置
REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":["app01.app_auth.MyAuthentication",]
}

# 局部使用,在视图类上写
authentication_classes=[MyAuthentication]
# 局部禁用
authentication_classes=[]

认证源码分析

1、APIView重写as_view方法使之没有csrf认证——>但还是正常执行 dispatch 方法,但是 dispatch方法被 APIView重写了——>dispatch 中执行了 self.initial 认证方法——>有认证,权限,频率

2、现在只是看认证源码self.perform_authentication(request)

3、但是self.perform_authentication(request)就一句话:request.user,那么就需要去 drf 的 Request 对象中找 user 属性(方法)

@property
def user(self):
    # 先去判断当前对象中有没有'_user'这个属性,一开始肯定是没有的,因为用户是没有登录的
    if not hasattr(self, '_user'):
        with wrap_attributeerrors():
            # 没有用户,认证出用户
            self._authenticate()
    # 有用户,直接返回用户
    return self._user

4、Request 类中的 user 方法,刚开始来,没有_user,走 self._authenticate()

5、核心,就是Request类中的 _authenticate(self)

def _authenticate(self):
    
    # 遍历拿到一个认证器,进行认证
    # self.authenticators 配置的一堆认证类产生的认证类对象组成的 list
    # self.authenticators 就是在视图类中配置的:authentication_classes = [认证类1,认证类2] 的一个个认证类的对象:
    
    ————>self.authenticators ==》 [认证类1对象,认证类2对象]
    for authenticator in self.authenticators:
        try:
            
            # 认证器调用认证方法authenticate(认证类对象self,request对象)
            """
            def authenticate(self, request):
        		return (self.force_user, self.force_token)
            """
            # 返回值:登录的用户与认证的信息组成的 tuple
            # 并且该方法被try包裹,就代表该方法会抛异常,抛异常就代表认证失败
            user_auth_tuple = authenticator.authenticate(self) # self是request对象
        except exceptions.APIException:
            self._not_authenticated()
            raise
		
        # 返回值的处理
        if user_auth_tuple is not None:
            self._authenticator = authenticator
            # 如果有返回值,就将 "登录用户" 与 "登录认证" 分别保存到 request.user / request.auth
            self.user, self.auth = user_auth_tuple
            return
	# 如果返回值user_auth_tuple为空,代表认证通过,但是没有 "登录用户" 与 "登录认证信息",代表游客
    self._not_authenticated()

认证组件的使用

1、写一个认证类,继承 BaseAuthentication,重写 authenticate

# app01_auth.py
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from app01.models import UserToken


class TokenAuthentication(BaseAuthentication):
    def authenticate(self, request):
        # 认证逻辑,如果认证通过,返回两个值
        # 如果认证失败,抛出AuthenticationFailed异常
        token = request.data.get('token')
        if token:
            user_token = UserToken.objects.filter(token=token).first()

            # 认证通过
            if user_token:
                return UserToken.user, token
            else:
                raise AuthenticationFailed('认证失败')
        else:
            raise AuthenticationFailed('请求地址中需要带token')

2、将认证类添加到需要认证视图类的authentication_classes = [认证类1]

# views.py
from rest_framework.viewsets import ModelViewSet
from rest_framework.views import APIView
from rest_framework.response import Response
from app01.models import Books, UserInfo, UserToken
from app01.ser import BooksSerializer
from app01.app01_auth import TokenAuthentication
import uuid


# 查看Books需要经过认证才能查看
class BooksView(ModelViewSet):
    authentication_classes = [TokenAuthentication]

    queryset = Books.objects.all()
    serializer_class = BooksSerializer


# 登录视图,登录后获得token,后续用token认证
class LoginView(APIView):

    def post(self, request):
        response_msg = {'status': 200, 'msg': ''}
        username = request.data.get('username')
        password = request.data.get('password')
        user_obj = UserInfo.objects.filter(username=username, password=password).first()

        if user_obj:
            # 登录成功生成一个随机字符串
            token = uuid.uuid4()
            
            # 存到UserToken表中,update_or_create有就更新,没有就新增
            UserToken.objects.update_or_create(defaults={'token': token}, user=user_obj)
            response_msg['msg'] = '登录成功'
            response_msg['token'] = token
        else:
            response_msg['msg'] = '账户或密码错误'
            response_msg['status'] = 204
        return Response(response_msg)

到此这篇关于drf-router和authenticate认证源码分析的文章就介绍到这了,更多相关drf-router和authenticate内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

[!--infotagslink--]

相关文章

  • 手机未实名认证被停机了怎么办?中国移动/联通/电信手机号实名认证方法

    ,“手机实名制”就是每一个手机号码对应一个身份证,对应唯一真实的主人。如果不认证可能会陆续遭到停机,这该怎么办呢?手机怎么认证呢?下面就详情来看看移动联通电信手机号实名认证方式吧...2016-11-01
  • asp.net core MVC之实现基于token的认证

    这篇文章主要介绍了asp.net core MVC之实现基于token的认证,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-05-07
  • 关于C#.net winform程序验证moss的集成身份认证实例

    因为网站使用的是windows集成认证,所以遇到了权限问题,需要输入密码。使操作和用户体验非常不方便,研究了好久没有找到好的方法,最后终于让我踏破铁鞋总结出了下面的方法...2020-06-25
  • ASP.NET Core使用JWT认证授权的方法

    这篇文章主要介绍了ASP.NET Core使用JWT认证授权的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
  • Nginx上配置Basic Authorization登录认服务证的教程

    现在我们所使用的包括社交网络API等开放平台授权获得用户的用户名和密码一般有两种认证方式,一种是Basic Auth,一种是OAuth,这里我们就来看一下Nginx上配置Basic Authorization登录认服务证的教程...2016-08-27
  • ASP.NET Core学习之使用JWT认证授权详解

    这篇文章主要给大家介绍了关于ASP.NET Core学习之使用JWT认证授权的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用ASP.NET Core具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2021-09-22
  • .net core webapi jwt 更为清爽的认证详解

    这篇文章主要介绍了.net core webapi jwt 更为清爽的认证详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2021-09-22
  • Apache如何增加.htaccess文件增加用户认证

    首先用htpasswd创建一个密码文件:比如文件名叫做my.passwd /home/apache/bin/htpasswd -c -b my.passwd myusername mypassword 如果增加帐号: /home/apache/bin/htpasswd...2016-01-28
  • Springboot shiro认证授权实现原理及实例

    这篇文章主要介绍了Springboot shiro认证授权实现原理及实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-11
  • 浅析MongoDB之安全认证

    MongoDB是基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。默认情况下,MongoDB实例启动运行时是没有启用用户访问权限控制的,在实例本机服务器上都可以随意连接到实例进行各种操作,MongoDB不会对连接客户端进行用户验证...2021-06-26
  • Nginx用户认证配置方法详解(域名/目录)

    Nginx超级强大它可以单独为一个域名设置用户认证,方法也很简单我们只要生成用户认证的用户名和密码,然后再Nginx添加auth认证配置即可...2016-01-27
  • asp.net5中的用户认证与授权(1)

    Visual Studio 2015 Preview 除了给我们带了了C# 6.0的新语法、跨移动的开发以外,还给我们带来了ASP.NET5(也就是之前被称作下一代ASP.NET的ASP.NET vNext)。本文给大家介绍asp.net5中的用户认证与授权(1),需要的朋友可以参考下...2021-09-22
  • 利用go-zero在Go中快速实现JWT认证的步骤详解

    这篇文章主要介绍了如何利用go-zero在Go中快速实现JWT认证,本文分步骤通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧...2020-10-26
  • python-jwt用户认证食用教学的实现方法

    这篇文章主要介绍了python-jwt用户认证食用教学的实现方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-01-19
  • 使用Nginx实现HTTPS双向验证的方法

    这篇文章主要介绍了使用Nginx实现HTTPS双向验证的方法,涉及到单向验证和双向验证的区别介绍,本文介绍的非常详细,具有参考借鉴价值,感兴趣的朋友一起学习吧...2016-08-27
  • Nginx单向认证的安装配置方法

    这篇文章主要介绍了Nginx单向认证的安装配置方法,需要的朋友可以参考下...2016-01-27
  • SpringBoot+Vue+JWT的前后端分离登录认证详细步骤

    这篇文章主要介绍了SpringBoot+Vue+JWT的前后端分离登录认证,其实创建后端springboot工程也很简单,本文安装idea步骤一步步给大家详细介绍,需要的朋友可以参考下...2021-09-25
  • Asp.Net Core添加请求头自定义认证的示例

    这篇文章主要介绍了Asp.Net Core添加请求头自定义认证的示例,帮助大家更好的理解和学习使用.net技术,感兴趣的朋友可以了解下...2021-09-22
  • ASP.NET Core 实现基本认证的示例代码

    这篇文章主要介绍了ASP.NET Core 实现基本认证的示例代码吗,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
  • ASP.NET学习CORE中使用Cookie身份认证方法

    本篇文章主要给大家详细分析了ASP.NET学习CORE中使用Cookie身份认证方法以及相关的实例代码,有需要的朋友参考下吧。...2021-09-22