drf——认证、权限、频率源码分析、全局异常处理、自动生成接口文档、RBAC介绍

系列文章目录

drf
第一章 django web开发模式、api接口、api接口测试工具、restful规范、序列化反序列化、drf安装使用

第二章 drf的使用、APIView源码分析、Request源码分析、Serializer的序列化

第三章 Serializer的反序列化、字段与参数、局部与全局钩子、ModelSerializer使用

第四章 drf认证、权限、频率源码分析、全局异常处理、自动生成接口文档、RBAC介绍



一、认证源码分析

所有视图都是基于APIView

class APIView(View):
	# 获取认证配置
	authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
	# 
	settings = api_settings

然后APIView的as_view会运行dispatch方法

    def dispatch(self, request, *args, **kwargs):

        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
        	# 在此处运行了initial来处理认证
            self.initial(request, *args, **kwargs)
        return self.response

initial方法运行perform_authentication

    def initial(self, request, *args, **kwargs):
        self.format_kwarg = self.get_format_suffix(**kwargs)
        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme
        #此处运行认证相关方法
        self.perform_authentication(request)
        self.check_permissions(request)
        self.check_throttles(request)

perform_authentication将传入的user进行验证

    def perform_authentication(self, request):
        request.user

request的user将会进行登录认证

    def __init__(self, request, parsers=None, authenticators=None,
                 negotiator=None, parser_context=None):
        assert isinstance(request, HttpRequest), (
            'The `request` argument must be an instance of '
            '`django.http.HttpRequest`, not `{}.{}`.'
            .format(request.__class__.__module__, request.__class__.__name__)
        )

        self._request = request
        self.parsers = parsers or ()
        self.authenticators = authenticators or ()
        self.negotiator = negotiator or self._default_negotiator()
        self.parser_context = parser_context
        self._data = Empty
        self._files = Empty
        self._full_data = Empty
        self._content_type = Empty
        self._stream = Empty

        if self.parser_context is None:
            self.parser_context = {}
        self.parser_context['request'] = self
        self.parser_context['encoding'] = request.encoding or settings.DEFAULT_CHARSET

        force_user = getattr(request, '_force_auth_user', None)
        force_token = getattr(request, '_force_auth_token', None)
        if force_user is not None or force_token is not None:
            forced_auth = ForcedAuthentication(force_user, force_token)
            self.authenticators = (forced_auth,)

二、权限源码分析

所有视图都是基于APIView

class APIView(View):
	# 获取认证配置
	authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
	# 
	settings = api_settings

然后APIView的as_view会运行dispatch方法

    def dispatch(self, request, *args, **kwargs):

        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
        	# 在此处运行了initial来处理认证
            self.initial(request, *args, **kwargs)
        return self.response

initial方法运行check_permissions

    def initial(self, request, *args, **kwargs):
        self.format_kwarg = self.get_format_suffix(**kwargs)
        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme
        self.perform_authentication(request)
        #此处运行认证相关方法
        self.check_permissions(request)
        self.check_throttles(request)

check_permissions将会进行权限的验证

    def check_permissions(self, request):
    	# 不断从权限列表获取权限类然后判断
        for permission in self.get_permissions():
            if not permission.has_permission(request, self):
                self.permission_denied(
                    request,
                    message=getattr(permission, 'message', None),
                    code=getattr(permission, 'code', None)
                )

三、频率源码分析

所有视图都是基于APIView

class APIView(View):
	# 获取认证配置
	authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
	# 
	settings = api_settings

然后APIView的as_view会运行dispatch方法

    def dispatch(self, request, *args, **kwargs):

        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
        	# 在此处运行了initial来处理认证
            self.initial(request, *args, **kwargs)
        return self.response

initial方法运行check_throttles

    def initial(self, request, *args, **kwargs):
        self.format_kwarg = self.get_format_suffix(**kwargs)
        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme
        self.perform_authentication(request)
        self.check_permissions(request)
        #此处运行频率相关方法
        self.check_throttles(request)

check_throttles将会对需要限制的资源进行访问限制

    def check_throttles(self, request):
        throttle_durations = []
        for throttle in self.get_throttles():
            if not throttle.allow_request(request, self):
                throttle_durations.append(throttle.wait())

        if throttle_durations:
            durations = [
                duration for duration in throttle_durations
                if duration is not None
            ]
            duration = max(durations, default=None)
            self.throttled(request, duration)

四、全局异常处理

drf配置文件中,已经配置了,但是它不只能对drf的异常做出处理,而我们需要的是能对各种异常都进行处理,以便提高代码的健壮性(鲁棒性)

drf的配置文件的默认配置文件

'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',

当触发drf的异常错误时会调用exception_handler来处理

def exception_handler(exc, context):
    if isinstance(exc, Http404):
        exc = exceptions.NotFound()
    elif isinstance(exc, PermissionDenied):
        exc = exceptions.PermissionDenied()

    if isinstance(exc, exceptions.APIException):
        headers = {}
        if getattr(exc, 'auth_header', None):
            headers['WWW-Authenticate'] = exc.auth_header
        if getattr(exc, 'wait', None):
            headers['Retry-After'] = '%d' % exc.wait

        if isinstance(exc.detail, (list, dict)):
            data = exc.detail
        else:
            data = {'detail': exc.detail}

        set_rollback()
        return Response(data, status=exc.status_code, headers=headers)

    return None

自定义全局异常处理函数

exc 为错误原因
context 为发生错误的函数 参数 求情等组成的字典

exc: list index out of range
context: {‘view’: <app01.views.UserApiView object at 0x0000024F4D011708>, ‘args’: (), ‘kwargs’: {}, ‘request’: <rest_framework.request.Request: GET ‘/user/’>}

from rest_framework.views import exception_handler
from rest_framework.response import Response

def common_exception_handler(exc, context):
    dict_code = {'code':10001}
    response = exception_handler(exc, context)
    if response:
        dict_code['msg'] = str(exc)
    else:
        dict_code['code'] = 10002
        dict_code['msg'] = str(exc)
    return Response(dict_code)



五、自动生成接口文档

第一种:写word、md提交到git上
第二种:使用接口文档平台,如公司自己开发、yapi(百度开源)、第三方接口文档平台

drf中自动生成接口文档

自动生成接口文档是在自动路由的基础上形成的也就是在ViewSetMixin的基础上才能实现

如coreapi,swagger

coreapi使用步骤
1.安装 pip install coreapi
2.加入路由

from rest_framework.documentation import include_docs_urls
        urlpatterns = [
            path('docs/', include_docs_urls(title='站点页面标题'))
        ]

3.配置文件

REST_FRAMEWORK = {
         'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
        }

例如:
urls.py

from django.contrib import admin
from django.urls import path
from rest_framework.routers import SimpleRouter

from app01 import views
from rest_framework.documentation import include_docs_urls

router=SimpleRouter()
router.register('book2',views.BookInfoViewSet,'book2')
urlpatterns = [
    path('docs/', include_docs_urls(title='站点页面标题')),
    path('admin/', admin.site.urls),
    path('user/', views.UserApiView.as_view({'get':'get'})),
]
urlpatterns+=router.urls

views.py

class UserApiView(ViewSetMixin,APIView):
    """
        get:
        返回所有用户信息.
    """
    def get(self, request):
        l = [1,2]
        print(l[1])
        return Response({'coe':'code'})

# 自动生成接口文档的测试
from rest_framework import generics
class BookListView(generics.ListAPIView):
    """
    返回所有图书信息.
    """
class BookListCreateView(generics.ListCreateAPIView):
    """
    get:
    返回所有图书信息.

    post:
    新建图书.
    """
from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
    """
    list:
    返回图书列表数据

    retrieve:
    返回图书详情数据

    latest:
    返回最新的图书数据

    read:
    修改图书的阅读量
    """

效果图:
在这里插入图片描述


六、RBAC介绍

RBAC是基于角色的访问控制(Role-Based Access Control )在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。

这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便

django的后台admin就有RBAC存在

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值