Django REST Framework的認證方式及自定義認證

1、基於Token進行用戶認證

建立相應數據庫python

class member_type(models.Model):
    mtype = models.CharField(max_length=50)
    def __unicode__(self):
        return self.mtype

class member(models.Model):
    username = models.CharField(max_length=30)
    password = models.CharField(max_length=100)
    email = models.EmailField()
    user_type = models.ForeignKey("member_type")
    def __unicode__(self):
        return self.username

class member_token(models.Model):
    user = models.OneToOneField(to=member)
    token = models.CharField(max_length=64)
    def __unicode__(self):
        return self.token

    

配置路由數據庫

from abyss import views
from django.conf.urls import url

urlpatterns = [
    url(r'^api/v1/auth$', views.AuthView.as_view(),name='auth'),
    url(r'^api/v1/order$', views.OrderView.as_view(),name='order'),
]

在setting文件中,添加rest framework應用django

INSTALLED_APPS = [
    'rest_framework',
]

配置視圖認證api

from rest_framework.views import APIView
from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions
from django.http import JsonResponse
from django.shortcuts import HttpResponse
import hashlib
import time

class Myauthentication(BaseAuthentication):
    '''認證類'''
    def authenticate(self, request):
        token = request._request.GET.get("token")
        token_obj = models.member_token.objects.filter(token=token).first()
        if not token_obj:
            raise exceptions.AuthenticationFailed('用戶認證失敗')
        return (token_obj.user, token_obj)  # 這裏返回值一次給request.user,request.auth

    def authenticate_header(self, request):
        pass

def make_token(user):
    ctime = str(time.time())
    hash=hashlib.md5(user.encode("utf-8"))
    hash.update(ctime.encode("utf-8"))
    return hash.hexdigest()

class AuthView(APIView):
    """登陸認證"""
    def dispatch(self, request, *args, **kwargs):
        return super(AuthView,self).dispatch(request,*args, **kwargs)
    def get(self,request, *args, **kwargs):
        return HttpResponse('get is ok')
    def post(self,request, *args, **kwargs):
        ret={'code':1000,'msg':"登陸成功",'token':None}
        try:
            user = request._request.POST.get("username")
            pwd = request._request.POST.get("password")
            obj = models.member.objects.filter(username=user,password=pwd).first()
            if not obj:
                ret['code'] = 1001
                ret['msg'] = "用戶名或密碼錯誤"
            else:
                token = make_token(user)
                models.member_token.objects.update_or_create(user=obj,defaults={"token":token})
                ret['token'] = token
        except exceptions as e:
            ret['code'] = 1002
            ret['msg'] = "請求異常"

        return JsonResponse(ret)

class OrderView(APIView):
    """查看訂單信息"""

    authentication_classes = [Myauthentication,]  #添加認證
    def get(self, request, *args, **kwargs):
        # request.user
        # request.auth
        ret = {'code': 1003, 'msg': "你的訂單已經完成", 'data': "買了一個媳婦"}
        return JsonResponse(ret, safe=True)

登陸認證,登陸後會生成token值瀏覽器

 

使用token進行訂單查詢:session

2、全局自定義認證

經過對Django rest framework認證的源碼分析知道,能夠直接在項目的settings.py配置文件中引入自定義的認證類,便可以對全部的url進行用戶認證流程app

在應用app目錄下建立utils包,在utils包下建立auth.py文件,內容爲自定義的認證類函數

from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions
from abyss import models

class Myauthentication(BaseAuthentication):
    '''認證類'''
    def authenticate(self, request):
        token = request._request.GET.get("token")
        token_obj = models.member_token.objects.filter(token=token).first()
        if not token_obj:
            raise exceptions.AuthenticationFailed('用戶認證失敗')

        # restframework會將元組賦值給request,以供後面使用
        return (token_obj.user, token_obj)  # 這裏返回值一次給request.user,request.auth

    def authenticate_header(self, request):
        pass

 settings.py中的REST_FRAMEWORK做爲key做爲配置,因此全局配置示例:源碼分析

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES':['abyss.utils.auth.Myauthentication',]
}

#其中寫認證的類的路徑,不要在views中,這裏我放在了utils目錄下auth.py中post

此外,由於開啓了全局認證,因此每一個接口視圖中:authentication_classes = [Myauthentication,] 就不須要設置了。

局部某個視圖不須要認證狀況,如認證AuthView應該是能夠直接訪問的,那就以下設置:

authentication_classes = []    #authentication_classes爲空,表明不須要認證

3、配置匿名用戶

匿名用戶配置

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES":['API.utils.auth.Authentication',],  
    #其中寫認證的類的路徑,不要在views中,這裏我放在了utils目錄下auth.py中
    "UNAUTHENTICATED_USER": lambda:"匿名",
    #匿名用戶配置,只須要函數或類的對應的返回值,對應request.user="匿名"
    "UNAUTHENTICATED_token": None,
    #匿名token,只須要函數或類的對應的返回值,對應request.auth=None

}

4、Django rest framework內置的認證類

1.BaseAuthentication

BaseAuthentication是django rest framework爲咱們提供了最基本的認證類,正如源碼流程同樣,該類中其中定義的兩個方法authenticate和authenticate_header(認證失敗返回的響應頭),使用時候重寫該兩個方法進行認證,正如示例:

class BaseAuthentication(object):
    """
    All authentication classes should extend BaseAuthentication.
    """

    def authenticate(self, request):
        """
        Authenticate the request and return a two-tuple of (user, token).
        """
        raise NotImplementedError(".authenticate() must be overridden.")

    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.
        """
        pass

 其它認證類:

##路徑:rest_framework.authentication  BasicAuthentication #基於瀏覽器進行認證,瀏覽器彈框 SessionAuthentication #基於django的session進行認證 RemoteUserAuthentication #基於django admin中的用戶進行認證,這也是官網的示例 TokenAuthentication #基於drf內部的token認證

 5、總結

1.自定義認證類:

繼承BaseAuthentication,重寫authenticate方法和authenticate_header(pass就能夠),authenticate()方法須要有三種狀況(返回元祖、出現異常、返回none)。

2.認證配置:

#全局認證
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES":['API.utils.auth.Authentication',]
}

#局部認證
authentication_classes = [BaseAuthentication,]

#是某個視圖不進行認證
authentication_classes =[]
相關文章
相關標籤/搜索