Django-Rest frameworw認證和許可權
阿新 • • 發佈:2019-01-24
一、認證已封裝好的類
from rest_framework.authentication import BaseAuthentication class BaseAuthentication(object): def authenticate(self, request): #三種返回結果 1、 return (user,auth) #當前認證處理後,認證環節結束,不在執行後面的認證了 2、 return None #不處理,讓後面認證處理 3、 raise raise #exceptions.AuthenticationFailed("使用者認證失敗") def authenticate_header(self, request): # 驗證失敗時,返回的響應頭WWW-Authenticate對應的值 pass class BasicAuthentication(BaseAuthentication): '請求頭認證' pass class SessionAuthentication(BaseAuthentication): 'session認證' pass class TokenAuthentication(BaseAuthentication): 'token認證,' pass
二、許可權已封裝好的類
from rest_framework.permissions import BasePermission class BasePermission(object): message = "許可權驗證失敗" #定製驗證的錯誤資訊 def has_permission(self, request, view): '判斷是否有許可權訪問當前請求' return True #/ False # GenericAPIView中get_object時呼叫 def has_object_permission(self, request, view, obj): '檢視繼承GenericAPIView,並在其中使用get_object時獲取物件時,觸發單獨物件許可權驗證' return True # / False class AllowAny(BasePermission): '任何人都能訪問,和沒設定一樣' def has_permission(self, request, view): return True class IsAuthenticated(BasePermission): '登入後,才能訪問' def has_permission(self, request, view): return request.user and request.user.is_authenticated class IsAdminUser(BasePermission): '只允許,admin使用者訪問' class IsAuthenticatedOrReadOnly(BasePermission): '登入後,請求方式允許(get , put) 才能訪問 ' class DjangoModelPermissions(BasePermission): '不清楚'
1、def authenticate_header(self, request): #作用
生成這樣的登入介面(瀏覽器自帶的登入介面)
三、認證示例展示
============*****============
1、使用者url傳入的token認證 #區域性 或 全域性類使用
2、請求頭認證
3. 多個認證規則
4.認證和許可權
============*****============
1、使用者url傳入的token認證
2、請求頭認證in url.py from django.conf.urls import url, include from web.viewsimport TestView urlpatterns = [ url(r'^test/', TestView.as_view()), ] in view.py 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, ] permission_classes = [] 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請求,響應內容') 方式二:(推薦)在使用區域性類 ,或者TestView不想使用全域性的類(認證、許可權等) class MyTokenAuthentication(object): authentication_classes = [TestAuthentication, ] permission_classes = [] class TestView(MyTokenAuthentication,APIView): #MyTokenAuthentication 要放在前面, #否則authentication_classes 就從全域性(settings)裡找 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請求,響應內容')
in url.py
from django.conf.urls import url, include
from web.viewsimport TestView
urlpatterns = [
url(r'^test/', TestView.as_view()),
]
in view.py
#!/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(':') # partition 切割和split類似,
if username == 'alex' and password == '123': # 但 'xxx:yyy'.partition(":") = ['xxx',':','yyy']
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): # 關注 1、使用者url傳入的token認證 的TestView使用
authentication_classes = [TestAuthentication, ]
permission_classes = []
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請求,響應內容')
3. 多個認證規則in url.py
from django.conf.urls import url, include
from web.views.s2_auth import TestView
urlpatterns = [
url(r'^test/', TestView.as_view()),
]
in view.py
#!/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 Test1Authentication(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()# 預設值為:None
else:
self.auth = None
(user,token)表示驗證通過並設定使用者名稱和Token;
AuthenticationFailed異常
"""
import base64
auth = request.META.get('HTTP_AUTHORIZATION', b'')
if auth:
auth = auth.encode('utf-8')
else:
return None
print(auth,'xxxx')
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'
pass
class Test2Authentication(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()# 預設值為:None
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.
"""
pass
class TestView(APIView):
authentication_classes = [Test1Authentication, Test2Authentication] # 某個認證處理完就結束了,之後的認證失效
permission_classes = [] # 許可權是每個類都要經過
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請求,響應內容')
4.認證和許可權
in url.py
from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'^test/', TestView.as_view()),
]
in view.py
#!/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.permissions import BasePermission
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()# 預設值為:None
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.
"""
pass
class TestPermission(BasePermission):
message = "許可權驗證失敗" # 錯誤資訊
def has_permission(self, request, view):
"""
判斷是否有許可權訪問當前請求
兩種返回結果
return True # 許可權驗證通過,執行下一個許可權類
return False # 檢測為False 然後就raise 報錯
"""
if request.user == "管理員":
return True
# GenericAPIView中get_object時呼叫
def has_object_permission(self, request, view, obj):
"""
檢視繼承GenericAPIView,並在其中使用get_object時獲取物件時,觸發單獨物件許可權驗證
Return `True` if permission is granted, `False` otherwise.
:param request:
:param view:
:param obj:
:return: True有許可權;False無許可權
"""
if request.user == "管理員":
return True
class TestView(APIView):
# 認證的動作是由request.user觸發
authentication_classes = [TestAuthentication, ]
# 許可權
# 迴圈執行所有的許可權
permission_classes = [TestPermission, ]
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請求,響應內容')