BaseAuthentication 類: django rest framework 經過 BaseAuthentication 實現認證功能 不管是自定義的認證類仍是 rest framework 自帶的認證類都應該繼承 BaseAuthentication BaseAuthentication 中有兩個方法 authenticate 和 authenticate_header, 其中 authenticate 方法必須實現 若是用戶須要自定義認證方法則繼承 BaseAuthentication 重寫 authenticate 方法便可
models.pydjango
from django.db import models class UserInfo(models.Model): user_type_choices = ( (1, '普通用戶'), (2, 'VPI'), (3, 'SVPI'), ) user_type = models.IntegerField(choices=user_type_choices) username = models.CharField(max_length=32, unique=True) password = models.CharField(max_length=64) class UserToken(models.Model): user = models.OneToOneField('UserInfo', models.CASCADE) token = models.CharField(max_length=64)
APP_DIR/utils/auth.py # 在和 views.py 同級的目錄建立 utils 包, 在 utils 中建立 auth.py 文件, 將認證相關的代碼放入其中瀏覽器
from rest_framework import exceptions from rest_framework.authentication import BaseAuthentication from app01 import models # 實現自定義的認證類 class Authtication(BaseAuthentication): def authenticate(self, request): # 這兒的 request 對象不是 django 原生的 request 而是 rest_framework 內部進行封裝過的 request # 使用 request._request 調用 django 原生的 request 對象 token = request._request.GET.get('token') # 檢查用戶的 token 是否合法 token_obj = models.UserToken.objects.filter(token=token).first() if not token_obj: # rest_framework 會在內部捕捉這個異常並返回給用戶認證失敗的信息 raise exceptions.AuthenticationFailed('用戶認證失敗') # 在 rest_framework 內部會將這兩個字段賦值給request以供後續調用 return (token_obj.user, token_obj)
views.pyapp
from django.http import JsonResponse from rest_framework.views import APIView from app01.utils.auth import Authtication import hashlib import time # 生成 token 字符串 def md5(user): ctime = str(time.time()) m = hashlib.md5(bytes(user, encoding='utf-8')) m.update(bytes(ctime, encoding='utf-8')) return m.hexdigest() # 用戶登陸 class AuthView(APIView): def post(self, request): ret = {'code':1000, 'msg':None} try: user = request._request.POST.get('username') pwd = request._request.POST.get('password') obj = models.UserInfo.objects.filter(username=user, password=pwd).first() if not obj: ret['code'] = 1001 ret['msg'] = "用戶名或密碼錯誤" # 爲登陸用戶建立token token = md5(user) #存在更新 不存在建立 models.UserToken.objects.update_or_create(user=obj, defaults={'token':token}) ret['token'] = token except: ret['code'] = 1002 ret['msg'] = '請求異常' return JsonResponse(ret) # 業務代碼 class Order(APIView): # 註冊自定義的認證類, 能夠有多個, 從左到右進行認證匹配 authentication_classes = [Authtication,] def get(self, request): # request.user 這個值等於 Authtication 返回的元組的第一個值 # request.auth 這個值等於 Authtication 返回的元組的第二個值 ret = {'code':1000, 'msg':None, 'data':None} ret['data'] = '歡迎使用本系統' return JsonResponse(ret)
rest_framework 內置的認證類:ide
BasicAuthentication # 基於瀏覽器實現的 Basic 認證, ftp 使用網頁登陸時使用的就是 Basic 認證 SessionAuthentication # 基於 django 的 user.is_active 進行認證 TokenAuthentication # 簡單的基於 token 的認證 RemoteUserAuthentication # 簡單的遠程用戶認證明現
配置全局生效的認證類和匿名用戶:post
自定義的認證類若是每次都在指定的類中使用 authentication_classes 指定那麼就有可能出現大量的重複代碼 咱們能夠經過全局設置讓指定的認證類對繼承至 APIView 的全部類生效 settings.py REST_FRAMEWORK = { # 設置全局生效的認證類(能夠有多個) # app01 爲 django app 的名稱 # utils 爲 app 目錄下面的 utils 目錄(這個目錄必須包含 __init__.py 文件) # auth 爲 utils 目錄下面的 auth.py 文件 # Authtication 爲 auth.py 文件裏面的 Authtication 類 # 這兒的設置其實就是使用 from ... import ... 的路徑 'DEFAULT_AUTHENTICATION_CLASSES': ["app01.utils.auth.Authtication",], #匿名用戶配置 'UNAUTHENTICATED_USER': None, # 設置匿名用戶的用戶名, 默認爲 AnonymousUser, 使用 request.user 查看 'UNAUTHENTICATED_TOKEN': None, # 設置匿名用戶的 token, 默認爲 None, 使用 request.auth 查看 }
指定 View 類不使用全局的認證類:rest
在不使用全局認證類的 View 類中添加 authentication_classes = [] 或者 authentication_classes = ['xxxx'] # authentication_classes = [] 表示不使用認證 # authentication_classes = ['xxxx'], xxxx 表示當前類須要使用的認證類用於替換全局類