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请求,响应内容')

原文地址:https://www.cnblogs.com/-wenli/p/13228008.html