Drf03 / drf版本、认证、权限

目录

  • Drf03 / drf版本、认证、权限

    • 回顾和补充
    • 今日概要
    • 今日详细
      • 1.请求的封装
      • 2.版本
      • 3.认证(面试)
      • 作业:将认证的功能添加到呼啦圈中。

Drf03 / drf版本、认证、权限

回顾和补充

  1. restful规范

    1. 建议用https代替http
    2. 在URL中体现api,添加api标识
     https://www.cnblogs.com/xwgblog/p/11812244.html   # 错误
     https://www.cnblogs.com/api/xwgblog/p/11812244.html  # 正确
     https://api.cnblogs.com/xwgblog/p/11812244.html # 正确
    
     建议:https://www.cnblogs.com/api/...
    3. 在URL中要体现版本
     https://www.cnblogs.com/api/v1/userinfo/
     https://www.cnblogs.com/api/v2/userinfo/
    4. 一般情况下对于api接口,用名词不用动词。
     https://www.cnblogs.com/api/v1/userinfo/
    5. 如果有条件的话,在URL后面进行传递。
     https://www.cnblogs.com/api/v1/userinfo/?page=1&category=2
    6. 根据method不同做不同操作
     get/post/put/patch/delete
  2. 简述drf组件。
  3. 类继承关系
    class View(object):
     def dipatch(self):
         print(123)
    
    class APIView(View):
     def dipatch(self):
         method = getattr(self,"get")
         return method()
    
    class GenericAPIView(APIView):
     queryset = None
     serilizer_class = None
     def get_queryset(self):
         return self.queryset
    
     def get_serilizer(self,*arg,**kwargs):
         cls = self.get_serilizer_class()
         return cls(*arg,**kwargs)
    
     def get_serilizer_class(self):
         return self.serilizer_class
    class ListModelMixin(object):
     def list(self):
         queryset = self.get_queryset()
         ser = self.get_serilizer(queryset,many=True)
         return Reponse(ser.data)
    
    class ListAPIView(ListModelMixin,GenericAPIView):
     def get(self):
         return self.list(...)
    
    class TagView(ListAPIView):
     queryset = models.User.object.all()
     serilizer_class = TagSerilizer
    
    obj = TagView()
    x = obj.dispatch()
    给用户返回x
  4. 继承关系
    class View(object):
     def dipatch(self):
         print(123)
    
    class APIView(View):
     version_class = settings.xxx
     parser_class = settings.sxx
     permision_classes = []
    
     def dipatch(self):
    
         self.initial()
    
         method = getattr(self,"get")
         return method()
    
     def initial(self):
         self.version_class()
         self.parser_class()
         for item in self.permision_classes:
             item()
    
    class GenericAPIView(APIView):
     queryset = None
     serilizer_class = None
     def get_queryset(self):
         return self.queryset
    
     def get_serilizer(self,*arg,**kwargs):
         cls = self.get_serilizer_class()
         return cls(*arg,**kwargs)
    
     def get_serilizer_class(self):
         return self.serilizer_class
    class ListModelMixin(object):
     def list(self):
         queryset = self.get_queryset()
         ser = self.get_serilizer(queryset,many=True)
         return Reponse(ser.data)
    
    class ListAPIView(ListModelMixin,GenericAPIView):
     def get(self):
         return self.list(...)
    
    class TagView(ListAPIView):
     queryset = models.User.object.all()
     serilizer_class = TagSerilizer
     version_class = URLPathClass
     parser_class = JSONParser
     permission_classes = [Foo,Bar ]
    
    obj = TagView()
    x = obj.dispatch()
    给用户返回x

今日概要

  • request请求对象封装
  • 版本
  • 认证
  • 权限
  • 频率限制

今日详细

1.请求的封装

class HttpRequest(object):
    def __init__(self):
        pass

    @propery
    def GET(self):
        pass

    @propery
    def POST(self):
        pass

    @propery
    def body(self):
        pass

class Request(object):
    def __init__(self,request):
        self._request = request

    def data(self):
        if content-type == "application/json"
            reutrn json.loads(self._request.body.decode('urf-8'))
        elif content-type == "x-www-...":
            return self._request.POST

    def query_params(self):
        return self._reqeust.GET

req = HttpRequest()
request = Request(req)

request.data
request.query_prams
request._request.GET
request._request.POST
request._request.body

drf入口请求流程:

  • 路由

    urlpatterns = [
        url(r'^order/$', views.OrderView.as_view()),
    ]
  • 视图关系
    class View(object):
      @classonlymethod
        def as_view(cls, **initkwargs):
            def view(request, *args, **kwargs):
                return self.dispatch(request, *args, **kwargs)
            return view
    
    class APIView(View):
    
      @classmethod
        def as_view(cls, **initkwargs):
            view = super().as_view(**initkwargs)
            return csrf_exempt(view)
      def dispatch(self, request, *args, **kwargs):
            # 新request内部包含老request(_reuqest=老request)
            request = self.initialize_request(request, *args, **kwargs)
            self.request = request
    
            self.initial(request, *args, **kwargs)
    
            # 通过反射执行“get”方法,并传入新的request
            handler = getattr(self, request.method.lower())
            response = handler(request, *args, **kwargs) # get(requst)
            return self.response
    
    class OrderView(APIView):
    
        def get(self,request,*args,**kwargs):
            return Response('海狗')
    
    

2.版本

版本使用三步:

1.settings配置文件

REST_FRAMEWORK = {
    'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning',
    'ALLOWED_VERSIONS':['v1','v2'],
}

2.路由

路由分发
urlpatterns = [
    url(r'^api/(?P<version>\w+)/', include('api.urls')),
]
子路由
urlpatterns = [
    url(r'^order/$', views.OrderView.as_view()),
]

3.通过request.version可以取值

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

class OrderView(APIView):
    def get(self,request,*args,**kwargs):
        print(request.version)
        print(request.versioning_scheme)
        return Response('...')

    def post(self,request,*args,**kwargs):
        return Response('post')

源码流程:

class APIView(View):
    versioning_class = api_settings.DEFAULT_VERSIONING_CLASS

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

        # ###################### 第一步 ###########################
        """
        request,是django的request,它的内部有:request.GET/request.POST/request.method
        args,kwargs是在路由中匹配到的参数,如:
            url(r'^order/(\d+)/(?P<version>\w+)/$', views.OrderView.as_view()),
            http://www.xxx.com/order/1/v2/
        """
        self.args = args
        self.kwargs = kwargs

        """
        request = 生成了一个新的request对象,此对象的内部封装了一些值。
        request = Request(request)
            - 内部封装了 _request = 老的request
        """
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request

        self.headers = self.default_response_headers  # deprecate?

        try:
            # ###################### 第二步 ###########################
            self.initial(request, *args, **kwargs)

            执行视图函数。。

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

        # ############### 2.1 处理drf的版本 ##############
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme
        ...

    def determine_version(self, request, *args, **kwargs):
        if self.versioning_class is None:
            return (None, None)
        scheme = self.versioning_class() # obj = XXXXXXXXXXXX()
        return (scheme.determine_version(request, *args, **kwargs), scheme)

class OrderView(APIView):
    versioning_class = URLPathVersioning
    def get(self,request,*args,**kwargs):
        print(request.version)
        print(request.versioning_scheme)
        return Response('...')

    def post(self,request,*args,**kwargs):
        return Response('post')
class URLPathVersioning(BaseVersioning):
    """
    urlpatterns = [
        url(r'^(?P<version>[v1|v2]+)/users/$', users_list, name='users-list'),

    ]
    """
    invalid_version_message = _('Invalid version in URL path.')

    def determine_version(self, request, *args, **kwargs):
        version = kwargs.get(self.version_param, self.default_version)
        if version is None:
            version = self.default_version

        if not self.is_allowed_version(version):
            raise exceptions.NotFound(self.invalid_version_message)
        return version

使用(局部)

  • url中写version

    url(r'^(?P<version>[v1|v2]+)/users/$', users_list, name='users-list'),
    
  • 在视图中应用
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.request import Request
    from rest_framework.versioning import URLPathVersioning
    
    class OrderView(APIView):
    
        versioning_class = URLPathVersioning
        def get(self,request,*args,**kwargs):
            print(request.version)
            print(request.versioning_scheme)
            return Response('...')
    
        def post(self,request,*args,**kwargs):
            return Response('post')
    
  • 在settings中配置
    REST_FRAMEWORK = {
        "PAGE_SIZE":2,
        "DEFAULT_PAGINATION_CLASS":"rest_framework.pagination.PageNumberPagination",
        "ALLOWED_VERSIONS":['v1','v2'],
        'VERSION_PARAM':'version'
    }
    

使用(全局)推荐

  • url中写version

    url(r'^(?P<version>[v1|v2]+)/users/$', users_list, name='users-list'),
    
    url(r'^(?P<version>\w+)/users/$', users_list, name='users-list'),
    
  • 在视图中应用
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.request import Request
    from rest_framework.versioning import URLPathVersioning
    
    class OrderView(APIView):
        def get(self,request,*args,**kwargs):
            print(request.version)
            print(request.versioning_scheme)
            return Response('...')
    
        def post(self,request,*args,**kwargs):
            return Response('post')
    
  • 在settings中配置
    REST_FRAMEWORK = {
        "PAGE_SIZE":2,
        "DEFAULT_PAGINATION_CLASS":"rest_framework.pagination.PageNumberPagination",
        "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
        "ALLOWED_VERSIONS":['v1','v2'],
        'VERSION_PARAM':'version'
    }
    

3.认证(面试)

from django.conf.urls import url,include
from django.contrib import admin
from . import views
urlpatterns = [
    url(r'^login/$', views.LoginView.as_view()),
    url(r'^order/$', views.OrderView.as_view()),
    url(r'^user/$', views.UserView.as_view()),
]

import uuid
from django.shortcuts import render
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from rest_framework.versioning import URLPathVersioning
from rest_framework.views import APIView
from rest_framework.response import Response

from . import models

class LoginView(APIView):

    def post(self,request,*args,**kwargs):
        user_object = models.UserInfo.objects.filter(**request.data).first()
        if not user_object:
            return Response('登录失败')
        random_string = str(uuid.uuid4())
        user_object.token = random_string
        user_object.save()
        return Response(random_string)

class MyAuthentication:
    def authenticate(self, request):
        """
        Authenticate the request and return a two-tuple of (user, token).
        """
        token = request.query_params.get('token')
        user_object = models.UserInfo.objects.filter(token=token).first()
        if user_object:
            return (user_object,token)
        return (None,None)

class OrderView(APIView):
    authentication_classes = [MyAuthentication, ]
    def get(self,request,*args,**kwargs):
        print(request.user)
        print(request.auth)
        return Response('order')

class UserView(APIView):
    authentication_classes = [MyAuthentication,]
    def get(self,request,*args,**kwargs):
        print(request.user)
        print(request.auth)
        return Response('user')

源码分析

class Request:

    def __init__(self, request,authenticators=None):
        self._request = request
        self.authenticators = authenticators or ()

    @property
    def user(self):
        """
        Returns the user associated with the current request, as authenticated
        by the authentication classes provided to the request.
        """
        if not hasattr(self, '_user'):
            with wrap_attributeerrors():
                self._authenticate()
        return self._user

    def _authenticate(self):
        """
        Attempt to authenticate the request using each authentication instance
        in turn.
        """
        for authenticator in self.authenticators:
            try:
                user_auth_tuple = authenticator.authenticate(self)
            except exceptions.APIException:
                self._not_authenticated()
                raise

            if user_auth_tuple is not None:
                self._authenticator = authenticator
                self.user, self.auth = user_auth_tuple
                return

        self._not_authenticated()

    @user.setter
    def user(self, value):
        """
        Sets the user on the current request. This is necessary to maintain
        compatibility with django.contrib.auth where the user property is
        set in the login and logout functions.

        Note that we also set the user on Django's underlying `HttpRequest`
        instance, ensuring that it is available to any middleware in the stack.
        """
        self._user = value
        self._request.user = value
class APIView(View):
    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES

    def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        # ###################### 第一步 ###########################
        """
        request,是django的request,它的内部有:request.GET/request.POST/request.method
        args,kwargs是在路由中匹配到的参数,如:
            url(r'^order/(\d+)/(?P<version>\w+)/$', views.OrderView.as_view()),
            http://www.xxx.com/order/1/v2/
        """
        self.args = args
        self.kwargs = kwargs

        """
        request = 生成了一个新的request对象,此对象的内部封装了一些值。
        request = Request(request)
            - 内部封装了 _request = 老的request
            - 内部封装了 authenticators = [MyAuthentication(), ]
        """
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request

    def initialize_request(self, request, *args, **kwargs):
        """
        Returns the initial request object.
        """
        parser_context = self.get_parser_context(request)

        return Request(
            request,
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(), # [MyAuthentication(),]
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )

    def get_authenticators(self):
        """
        Instantiates and returns the list of authenticators that this view can use.
        """
        return [ auth() for auth in self.authentication_classes ]

class LoginView(APIView):
    authentication_classes = []
    def post(self,request,*args,**kwargs):
        user_object = models.UserInfo.objects.filter(**request.data).first()
        if not user_object:
            return Response('登录失败')
        random_string = str(uuid.uuid4())
        user_object.token = random_string
        user_object.save()
        return Response(random_string)

class OrderView(APIView):
    # authentication_classes = [TokenAuthentication, ]
    def get(self,request,*args,**kwargs):
        print(request.user)
        print(request.auth)
        if request.user:
            return Response('order')
        return Response('滚')

class UserView(APIView):
    同上

总结

当用户发来请求时,找到认证的所有类并实例化成为对象列表,然后将对象列表封装到新的request对象中。

以后在视图中调用request.user

在内部会循环认证的对象列表,并执行每个对象的authenticate方法,该方法用于认证,他会返回两个值分别会赋值给
request.user/request.auth

作业:将认证的功能添加到呼啦圈中。

  • 登录表
  • 登录视图
  • 写认证类
  • 应用认证类:全局应用
  • Login视图不应用认证

原文地址:https://www.cnblogs.com/liubing8/p/11823653.html

时间: 2024-11-06 09:08:30

Drf03 / drf版本、认证、权限的相关文章

DRF 版本 认证

DRF的版本 版本控制是做什么用的, 我们为什么要用 首先我们要知道我们的版本是干嘛用的呢~~大家都知道我们开发项目是有多个版本的~~ 当我们项目越来越更新~版本就越来越多~~我们不可能新的版本出了~以前旧的版本就不进行维护了~~~ 那我们就需要对版本进行控制~~这个DRF也给我们提供了一些封装好的版本控制方法~~ 版本控制怎么用 之前我们学视图的时候知道APIView,也知道APIView返回View中的view函数,然后调用的dispatch方法~ 那我们现在看下dispatch方法~~看下

版本,认证,权限

版本 DRF中版本 导入 from rest_framework.versioning import 全局配置版本控制系统 /v1/books/    是在 URL加查询参数 # DRF的配置 REST_FRAMEWORK = { # 配置默认使用的版本控制类 'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning', 'DEFAULT_VERSION': 'v1', # 默认的版本 'ALLOWED_VE

DRF 版本、认证、权限、限制、解析器和渲染器

目录 一.DRF之版本控制 为什么要有版本控制? DRF提供的版本控制方案 版本的使用 全局配置 局部配置(使用较少) 二.DRF之认证 内置的认证 步骤 三.DRF之权限 1.自定义一个权限类 2.权限 局部配置 3.权限 全局配置 四.DRF之限制 1.使用自定义限制类 1.1自定义一个限制类 1.2限制 局部配置 1.3限制 全局配置 2.使用内置限制类 2.1定义内置限制类 2.2全局配置 五.DRF之分页 1.为什么要使用分页 2.DRF使用分页器 2.1分页模式 2.2全局配置 2.

SAP云解决方案和企业本地部署(On-Premise)混合架构下的安全认证权限管理

SAP提供了用户认证.权限管理和单点登录等安全相关的解决方案.但是随着云平台的兴起,企业已经部署的安全解决方案如何与云平台的安全解决方案集成呢?这是摆在我们面前的一个问题,而且是一个至关重要.需要认真思考的问题. 本文将探讨SAP提供的本地部署和云平台的安全解决方案产品集:SAP Single Sign-On, SAP Cloud Platform Identity Authentication, SAP Identity Management, 和SAP Cloud Platform Iden

drf 三大认证详解

目录 drf 三大认证: 认证: 权限: 认证与权限组件绑定使用: 频率: 多方式登录: drf 三大认证: 认证: # 全局配置: -在全局(认证组件只能决定request.user,不是断定权限的地方,所以一般配置全局) REST_FRAMEWORK = { # 认证组件 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework_jwt.authentication.JSONWebTokenAuthentication' ], } # 局部禁用(

C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本 - 数据权限增强、范围权限增强

并不是不想做B\S的管理工具,只是精力实在不够,由于用户权限管理组件是基础组件.所以C\S的也无妨,不会有几个人在乎Oracle,SQLServer是否不b\s的,注重的是功能性能,请大家不要纠结与是否B\S还是C\S上. 实现的方法.设计的界面.数据库结构的设计.底层DLL方法的函数调用,都可以参考,毕竟自己全部实现一个,耗费太多精力,不如拿过来用用参考,按自己的需要修改几下就可以用了,省心省事省力,腰不疼腿不酸,没必要浪费生命. 由于公司的组织机构庞大.网点非常多,所以数据权限的设置也非常复

【原】无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限

开发环境搭建参见<[原]无脑操作:IDEA + maven + SpringBoot + JPA + Thymeleaf实现CRUD及分页> 需求: ① 除了登录页面,在地址栏直接访问其他URL,均跳转至登录页面 ② 登录涉及帐号和密码,帐号错误提示帐号错误,密码错误提示密码错误 ③ 登录成功跳转至首页,首页显示登录者帐号信息,并有注销帐号功能,点击注销退出系统 ------------------------------------------------------------------

drf三大认证:认证组件-权限组件-权限六表-自定义认证组件的使用

三大认证工作原理简介 源码分析: from rest_framework.views import APIView 源码分析入口: 内部的三大认证方法封装: 三大组件的原理分析: 权限六表分析 基于用户权限访问控制的认证(RBAC):Role-Based-Access-Control;基于auth的认证规则(了解). Django框架采用的是RBAC认证规则:通常分为:三表规则.五表规则.Django采用的是六表规则. 三表:用户表.角色表.权限表 五表:用户表.角色表.权限表.用户角色关系表.

drf三大认证

源码分析 dispath方法内 self.initial(request, *args, **kwargs) 进入三大认证 # 认证组件:校验用户(游客,合法用户,非法用户) # 游客:代表校验通过直接进入下一步校验, # 合法用户:代表校验通过,将用户存储在request.user中,在进入下一步校验 # 非法用户:代表校验失败,抛出异常,返回403权限异常结果 self.perform_authentication(request) # 权限组件:校验用户权限,必须登录,所有用户登录读写,游