REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.TokenAuthentication', 'rest_framework_simplejwt.authentication.JWTAuthentication', ],
系統提供四種基本認證,其餘的能夠本身定製,或者使用第三方html
參考:http://www.javashuo.com/article/p-bayaaffu-nq.htmlpython
通常用於測試,根據用戶的用戶名和密碼煙瘴,經過後,BasicAuthentication
提供如下憑據:數據庫
.request.user
將是一個Django User
實例。 django
.request.auth
會的None
。後端
基於令牌的簡單HTTP身份驗證方案。令牌認證適用於客戶端 - 服務器設置,例如本機桌面和移動客戶端。api
使用TokenAuthentication,需在
INSTALLED_APPS
設置中另外包含app服務器
INSTALLED_APPS = ( ... 'rest_framework.authtoken' )
注意:確保manage.py migrate
在更改設置後運行。該rest_framework.authtoken
應用程序提供Django數據庫遷移。session
使用Django的默認會話後端進行身份驗證。會話身份驗證適用於與您的網站在同一會話上下文中運行的AJAX客戶端。app
若是成功經過身份驗證,請SessionAuthentication
提供如下憑據。 ide
request.user將是一個Django User實例。
request.auth會的None。
參考 django server之間經過remote user 相互調用 和 django server之間經過remote user 相互調用
一、認證必須與受權配合使用,只認證,系統根本不作限制。必須受權限制才生效
取消受權,正常提取數據
class UserListView(generics.ListAPIView): authentication_classes = [BasicAuthentication,SessionAuthentication, TokenAuthentication] #permission_classes = [IsAuthenticated] queryset = models.CustomUser.objects.all() serializer_class = serializers.UserSerializer
二、加上受權,用BasicAuthentication 去認證,
class UserListView(generics.ListAPIView): authentication_classes = [BasicAuthentication,SessionAuthentication, TokenAuthentication] permission_classes = [IsAuthenticated] queryset = models.CustomUser.objects.all() serializer_class = serializers.UserSerializer
訪問的時候,html彈出輸入用戶名密碼的窗體。
三、加上受權,用BasicAuthentication之外的去認證,則出現未受權提醒,但不彈出窗體
SessionAuthentication是和BasicAuthentication配合使用的,用basic彈出窗體,輸入用戶密碼後,session會認證有效。
class UserListView(generics.ListAPIView): authentication_classes = [SessionAuthentication, TokenAuthentication,BasicAuthentication] permission_classes = [IsAuthenticated] queryset = models.CustomUser.objects.all() serializer_class = serializers.UserSerializer
3、django rest的權限與認證分析
一、APIView的調度入口 APIView的dispath(self, request, *args, **kwargs)
二、調度的全部任務(看認證,看權限,看訪問品讀) dispath方法內 self.initial(request, *args, **kwargs) 進入三大認證 # 認證組件:校驗用戶 - 遊客、合法用戶、非法用戶 # 遊客:表明校驗經過,直接進入下一步校驗(權限校驗) # 合法用戶:表明校驗經過,將用戶存儲在request.user中,再進入下一步校驗(權限校驗) # 非法用戶:表明校驗失敗,拋出異常,返回403權限異常結果 self.perform_authentication(request) # 權限組件:校驗用戶權限 - 必須登陸、全部用戶、登陸讀寫遊客只讀、自定義用戶角色 # 認證經過:能夠進入下一步校驗(頻率認證) # 認證失敗:拋出異常,返回403權限異常結果 self.check_permissions(request) # 頻率組件:限制視圖接口被訪問的頻率次數 - 限制的條件(IP、id、惟一鍵)、頻率週期時間(s、m、h)、頻率的次數(3/s) # 沒有達到限次:正常訪問接口 # 達到限次:限制時間內不能訪問,限制時間達到後,能夠從新訪問 self.check_throttles(request)
三、 認證組件(authenticatication)
在view中設置,只對該view有效,在setting.py中設置,對全部view有效。 兩處都設置,view的設置有效
Request類的 方法屬性 user 的get方法 => self._authenticate() 完成認證 認證的細則: # 作認證 def _authenticate(self): # 遍歷拿到一個個認證器,進行認證 # self.authenticators配置的一堆認證類產生的認證類對象組成的 list for authenticator in self.authenticators: try: # 認證器(對象)調用認證方法authenticate(認證類對象self, request請求對象) # 返回值:登錄的用戶與認證的信息組成的 tuple # 該方法被try包裹,表明該方法會拋異常,拋異常就表明認證失敗 user_auth_tuple = authenticator.authenticate(self) except exceptions.APIException: self._not_authenticated() raise # 返回值的處理 if user_auth_tuple is not None: self._authenticator = authenticator # 如何有返回值,就將 登錄用戶 與 登錄認證 分別保存到 request.user、request.auth self.user, self.auth = user_auth_tuple return # 若是返回值user_auth_tuple爲空,表明認證經過,可是沒有 登錄用戶 與 登錄認證信息,表明遊客 self._not_authenticated() 四、權限組件(permissions)
在view中設置,只對該view有效,在setting.py中設置,對全部view有效。 兩處都設置,view的設置有效
self.check_permissions(request) 認證細則: def check_permissions(self, request): # 遍歷權 限對象列表獲得一個個權限對象(權限器),進行權限認證 for permission in self.get_permissions(): # 權限類必定有一個has_permission權限方法,用來作權限認證的 # 參數:權限對象self、請求對象request、視圖類對象 # 返回值:有權限返回True,無權限返回False if not permission.has_permission(request, self): self.permission_denied( request, message=getattr(permission, 'message', None) ) 五、自定義認證類 ```python """ 1) 建立繼承BaseAuthentication的認證類 2) 實現authenticate方法 3) 實現體根據認證規則 肯定遊客、非法用戶、合法用戶 4) 進行全局或局部配置 認證規則 i.沒有認證信息返回None(遊客) ii.有認證信息認證失敗拋異常(非法用戶) iii.有認證信息認證成功返回用戶與認證信息元組(合法用戶) """ ``` 七、自定義認證舉例: utils/authentications.py ```python # 自定義認證類 # 1)繼承BaseAuthentication類 # 2)從新authenticate(self, request)方法,自定義認證規則 # 3)認證規則基於的條件: # 沒有認證信息返回None(遊客) # 有認證信息認證失敗拋異常(非法用戶) # 有認證信息認證成功返回用戶與認證信息元組(合法用戶) # 4)徹底視圖類的全局(settings文件中)或局部(確切的視圖類)配置 from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from . import models class MyAuthentication(BaseAuthentication): """ 同前臺請求頭拿認證信息auth(獲取認證的字段要與前臺約定) 沒有auth是遊客,返回None 有auth進行校驗 失敗是非法用戶,拋出異常 成功是合法用戶,返回 (用戶, 認證信息) """ def authenticate(self, request): # 前臺在請求頭攜帶認證信息, # 且默認規範用 Authorization 字段攜帶認證信息, # 後臺固定在請求對象的META字段中 HTTP_AUTHORIZATION 獲取 auth = request.META.get('HTTP_AUTHORIZATION', None) # 處理遊客 if auth is None: return None # 設置一下認證字段小規則(兩段式):"auth 認證字符串" auth_list = auth.split() # 校驗合法仍是非法用戶 if not (len(auth_list) == 2 and auth_list[0].lower() == 'auth'): raise AuthenticationFailed('認證信息有誤,非法用戶') # 合法的用戶還須要從auth_list[1]中解析出來 # 注:假設一種狀況,信息爲abc.123.xyz,就能夠解析出admin用戶;實際開發,該邏輯必定是校驗用戶的正常邏輯 if auth_list[1] != 'abc.123.xyz': # 校驗失敗 raise AuthenticationFailed('用戶校驗失敗,非法用戶') user = models.User.objects.filter(username='admin').first() if not user: raise AuthenticationFailed('用戶數據有誤,非法用戶') return (user, None) ``` 七、 系統權限類,共如下四種 1)AllowAny: 認證規則所有返還True:return True 遊客與登錄用戶都有全部權限 2) IsAuthenticated: 認證規則必須有登錄的合法用戶:return bool(request.user and request.user.is_authenticated) 遊客沒有任何權限,登錄用戶纔有權限 3) IsAdminUser: 認證規則必須是後臺管理用戶:return bool(request.user and request.user.is_staff) 遊客沒有任何權限,登錄用戶纔有權限 4) IsAuthenticatedOrReadOnly 認證規則必須是隻讀請求或是合法用戶: return bool( request.method in SAFE_METHODS or request.user and request.user.is_authenticated ) 遊客只讀,合法用戶無限制 """
在view中,只對本view有效 # api/views.py from rest_framework.permissions import IsAuthenticated class TestAuthenticatedAPIView(APIView): permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): return APIResponse(0, 'test 登陸才能訪問的接口 ok') # 由於默認全局setting.py配置的權限類是AllowAny,對全局有效 # settings.py REST_FRAMEWORK = { # 權限類配置 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.AllowAny', ], } 八、自定義權限類
參考:https://sunscrapers.com/blog/django-rest-framework-login-and-authentication/
1) 建立繼承BasePermission的權限類 2) 實現has_permission方法 3) 實現體根據權限規則 肯定有無權限 4) 進行全局或局部配置 認證規則 i.知足設置的用戶條件,表明有權限,返回True ii.不知足設置的用戶條件,表明有權限,返回False """ ``` 九、自定義權限實例 # utils/permissions.py from rest_framework.permissions import BasePermission from django.contrib.auth.models import Group class MyPermission(BasePermission): def has_permission(self, request, view): # 只讀接口判斷 r1 = request.method in ('GET', 'HEAD', 'OPTIONS') # group爲有權限的分組 group = Group.objects.filter(name='管理員').first() # groups爲當前用戶所屬的全部分組 groups = request.user.groups.all() r2 = group and groups r3 = group in groups # 讀接口你們都有權限,寫接口必須爲指定分組下的登錄用戶 return r1 or (r2 and r3) # 遊客只讀,登陸用戶只讀,只有登陸用戶屬於 管理員 分組,才能夠增刪改 from utils.permissions import MyPermission class TestAdminOrReadOnlyAPIView(APIView): permission_classes = [MyPermission] # 全部用戶均可以訪問 def get(self, request, *args, **kwargs): return APIResponse(0, '自定義讀 OK') # 必須是 自定義「管理員」分組 下的用戶 def post(self, request, *args, **kwargs): return APIResponse(0, '自定義寫 OK')