• Django Rest Framework组件:认证和授权模块BaseAuthentication


    视图FBV与CBV模板

    FBV:在urls.py中一个url对应一个函数,如以下:

    path('^user/', views.users)  FBV
    path('^student/', views.student.as_views())  CBV
    #FBV:一个url对应一个函数
    def users(request):
        if request.method  == "GET":
            return HttpResponse(json.dumps((uers)))
        if request.method == "POST":
            pass
        if request.method  == "PUT":
            pass
        if request.method  == "Delete":
            pass
    
    #CBV:一个url对应一个类
    #CBV基于反射:请求方法的不同,执行不同的方法
    # 原理:url路由-》view方法-》dispatch方法:Get、、
    from django.views import View
    class student(View):
        def dispatch(self,request,*args,**kwargs):
            #
            print("before")
            #执行父类的dispatch方法
            ret = super(student,self).dispatch(request,*args,**kwargs)        print("after")
            return ret
    
        def get(self,request,*args,**kwargs):
            return HttpResponse("GET")
        def post(self,request,*args,**kwargs):
            return HttpResponse("POST")
        def put(self,request,*args,**kwargs):
            return HttpResponse("PUT")
        def delete(self,request,*args,**kwargs):
            return HttpResponse("DELETE")

    上面两种视图模板,CBV更适合我们开发,而对于CBV模板在Django rest 框架中开发流程如下:

    url.py

    from django.conf.urls import url, include
    from app名.views import TestView
     
    urlpatterns = [
        url(r'^test/', TestView.as_view()),
    ]

    views.py

    from rest_framework.views import APIView
    from rest_framework.response import Response
     
     
    class TestView(APIView):
        def dispatch(self, request, *args, **kwargs):
            """
            请求到来之后,都要执行dispatch方法,dispatch方法根据请求方式不同触发 get/post/put等方法
             
            注意:APIView中的dispatch方法有好多好多的功能
            """
            return super().dispatch(request, *args, **kwargs)
     
        def get(self, request, *args, **kwargs):
            return Response('GET请求,响应内容')
     
        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')
     
        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

    CSRF的免除

    对于FBV:单个函数免除csrf
    1.先在视图下导入from django.views.decorators.csrf import csrf_exempt
    2.给单个函数加上 @csrf_exempt


    对于CBV:单个函数免除csrf
    1.先在视图下导入from django.utils.decorators import method_decorator
    2.给类下单个函数加上  @method_decorator(csrf_exempt)

        注意:你可以把它加在子类重写的dispatch方法上,当子类的dispatch执行时通过super执行父类的dispatch方法,再通过反射找到子类相应的函数去执行。

    Token认证

    局部配置:只对单个URL对应的视图函数有效。

    #认证三步走:
    1.对需要认证的url对应的CBV,写一个认证类,里面必须包括两个方法:
    authenticate:具体验证工作这个函数中做
    authenticate_header:验证失败响应头返回值设置
    2.认证类使用列表容器存储并赋值给
    authentication_classes
    authentication_classes = [TestAuthentication, ]
    3.认证成功返回元组:
    return ('登录用户', '用户token')
    可以通过request.user获取

    1.客户端通过url传入token方式

    from django.conf.urls import url, include
    from App名.views import TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_view()),
    ]
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.authentication import BaseAuthentication
    from rest_framework.request import Request
    from rest_framework import exceptions
    
    token_list = [
        'sfsfss123kuf3j123',
        'asijnfowerkkf9812',
    ]
    class TestAuthentication(BaseAuthentication):
        def authenticate(self, request):
            """
            用户认证,如果验证成功后返回元组: (用户,用户Token)
            :param request: 
            :return: 
                None,表示跳过该验证;
                    如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
                    self._authenticator = None
                    if api_settings.UNAUTHENTICATED_USER:
                        self.user = api_settings.UNAUTHENTICATED_USER()
                    else:
                        self.user = None
            
                    if api_settings.UNAUTHENTICATED_TOKEN:
                        self.auth = api_settings.UNAUTHENTICATED_TOKEN()
                    else:
                        self.auth = None
                (user,token)表示验证通过并设置用户名和Token;
                AuthenticationFailed异常
            """
            val = request.query_params.get('token')
            if val not in token_list:
                raise exceptions.AuthenticationFailed("用户认证失败")
    
            return ('登录用户', '用户token')
    
        def authenticate_header(self, request):
            """
            Return a string to be used as the value of the `WWW-Authenticate`
            header in a `401 Unauthenticated` response, or `None` if the
            authentication scheme should return `403 Permission Denied` responses.
            """
            # 验证失败时,返回的响应头WWW-Authenticate对应的值
            pass
    
    
    class TestView(APIView):
        authentication_classes = [TestAuthentication, ]def get(self, request, *args, **kwargs):
            print(request.user)
            print(request.auth)
            return Response('GET请求,响应内容')
    
        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')
    
        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

    2.通过请求头传入

    from django.conf.urls import url, include
    from app名.views import TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_view()),
    ]
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.authentication import BaseAuthentication
    from rest_framework.request import Request
    from rest_framework import exceptions
    
    token_list = [
        'sfsfss123kuf3j123',
        'asijnfowerkkf9812',
    ]
    
    
    class TestAuthentication(BaseAuthentication):
        def authenticate(self, request):
            """
            用户认证,如果验证成功后返回元组: (用户,用户Token)
            :param request: 
            :return: 
                None,表示跳过该验证;
                    如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
                    self._authenticator = None
                    if api_settings.UNAUTHENTICATED_USER:
                        self.user = api_settings.UNAUTHENTICATED_USER()
                    else:
                        self.user = None
            
                    if api_settings.UNAUTHENTICATED_TOKEN:
                        self.auth = api_settings.UNAUTHENTICATED_TOKEN()
                    else:
                        self.auth = None
                (user,token)表示验证通过并设置用户名和Token;
                AuthenticationFailed异常
            """
            import base64
            auth = request.META.get('HTTP_AUTHORIZATION', b'')
            if auth:
                auth = auth.encode('utf-8')
            auth = auth.split()
            if not auth or auth[0].lower() != b'basic':
                raise exceptions.AuthenticationFailed('验证失败')
            if len(auth) != 2:
                raise exceptions.AuthenticationFailed('验证失败')
            username, part, password = base64.b64decode(auth[1]).decode('utf-8').partition(':')
            if username == 'alex' and password == '123':
                return ('登录用户', '用户token')
            else:
                raise exceptions.AuthenticationFailed('用户名或密码错误')
    
        def authenticate_header(self, request):
            """
            Return a string to be used as the value of the `WWW-Authenticate`
            header in a `401 Unauthenticated` response, or `None` if the
            authentication scheme should return `403 Permission Denied` responses.
            """
            return 'Basic realm=api'
    
    
    class TestView(APIView):
        authentication_classes = [TestAuthentication, ]def get(self, request, *args, **kwargs):
            print(request.user)
            print(request.auth)
            return Response('GET请求,响应内容')
    
        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')
    
        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')
    

    全局配置:对所有URL对应的视图函数有效。

    1.在应用目录下和views.py文件同级下创建认证模块。然后在认证模块下创建认证类

    class TestAuthentication(BaseAuthentication):
        def authenticate(self, request):
            """
            用户认证,如果验证成功后返回元组: (用户,用户Token)
            :param request: 
            :return: 
                None,表示跳过该验证;
                    如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
                    self._authenticator = None
                    if api_settings.UNAUTHENTICATED_USER:
                        self.user = api_settings.UNAUTHENTICATED_USER()
                    else:
                        self.user = None
            
                    if api_settings.UNAUTHENTICATED_TOKEN:
                        self.auth = api_settings.UNAUTHENTICATED_TOKEN()
                    else:
                        self.auth = None
                (user,token)表示验证通过并设置用户名和Token;
                AuthenticationFailed异常
            """
            import base64
            auth = request.META.get('HTTP_AUTHORIZATION', b'')
            if auth:
                auth = auth.encode('utf-8')
            auth = auth.split()
            if not auth or auth[0].lower() != b'basic':
                raise exceptions.AuthenticationFailed('验证失败')
            if len(auth) != 2:
                raise exceptions.AuthenticationFailed('验证失败')
            username, part, password = base64.b64decode(auth[1]).decode('utf-8').partition(':')
            if username == 'alex' and password == '123':
                return ('登录用户', '用户token')
            else:
                raise exceptions.AuthenticationFailed('用户名或密码错误')
    
        def authenticate_header(self, request):
            """
            Return a string to be used as the value of the `WWW-Authenticate`
            header in a `401 Unauthenticated` response, or `None` if the
            authentication scheme should return `403 Permission Denied` responses.
            """
            return 'Basic realm=api'

    2.在settings配置文件中写入(添加刚才写的认证类的位置):

    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES':(
            '应用名.应用下的模块名.模块下的认证类名',
        )
    }

    3.urls.py文件不需要改动,views.py文件去掉authentication_classes = [TestAuthentication, ]

    from django.conf.urls import url, include
    from 应用名.views import TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_view()),
    ]
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    class TestView(APIView):
    
        def get(self, request, *args, **kwargs):
            # self.dispatch
            print(request.user)
            print(request.auth)
            return Response('GET请求,响应内容')
    
        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')
    
        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')
    
  • 相关阅读:
    HDU 4432 求因子+进制转换
    HDU 4438 概率 多个情况下的数学期望
    HDU 4424 并查集+贪心思想
    POJ 1611 记录节点数的并查集
    HDU 4430 二分查找
    HDU 4422 采蘑菇的小女孩
    最短路之SPFA模板
    zju pat1065. A+B and C (64bit)
    zju pat 1058 A+B in Hogwarts
    zju pat 1054 The Dominant Color
  • 原文地址:https://www.cnblogs.com/-wenli/p/13228008.html
Copyright © 2020-2023  润新知