DRF教程7-token認證


Authentication

  認證是將一個傳入的請求和一組標識憑據相關聯的機制,比如請求過來的用戶,或者用戶登錄時攜帶的token。

  然后權限策略就能使用這些憑據來決定是否允許這個請求。

  REST框架提供了多種開箱即用的方案,也允許你實施自定義的方案。

  認證總是在view的最開始運行,在權限檢查之前,在其他任何代碼被允許執行之前。

  request.user屬性通常會被設為contrib.auth 包下的User類。

  request.auth屬性被用做額外的認證信息。比如,作為一個請求簽名的認證token

  記住一點,認證機制自己並沒有允許或不允許一個傳入的請求,它只是簡單的標識請求攜帶的憑據。

認證方案設定

全局

REST_FRAMEWORK = {
    ...
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.BasicAuthentication'
    ),
}
#默認是session+basic
#對於前后端分離的項目,session認證一般刪掉,使用token,basic是必須放在這里的。
#在settings里設置默認認證類,然后會自上而下拿着請求來驗證,然后使用第一個成功認證的類返回用戶對象request.user (用戶信息)和request.auth(認證信息)。
#如果沒有類認證,request.user 會被設為 django.contrib.auth.models.AnonymousUser一個實例,request.auth 會設置為 None.

 

局部

from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

class ExampleView(APIView):
    authentication_classes = (SessionAuthentication, BasicAuthentication)
    permission_classes = (IsAuthenticated,)

    def get(self, request, format=None):
        content = {
            'user': unicode(request.user),  # `django.contrib.auth.User` instance.
            'auth': unicode(request.auth),  # None
        }
        return Response(content)

  

Unauthorized and Forbidden responses

 當一個未被認證的請求被拒絕時,有兩種合適的error code

401返回必須包含一個WWW-Authenticate header,指導客戶端需要如何認證。

403返回沒有包含WWW-Authenticate header。

使用哪種返回,取決於認證方案。雖然有多種認證方案在使用,但可能只有一個方案用於決定返回的類型。

在確定響應類型時,將使用視圖上設置的第一個身份驗證類

注意:當一個請求被成功認證時,但還是被拒絕執行請求,這種情況下,不論時哪種認證方案,總是使用403返回。

 

authentication.py源碼分析

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
#所有認證類都是基於它擴展

  

BasicAuthentication

這個方案使用HTTP Basic Authentication,使用用戶的username和password進行簽名。一般只適合用於測試。

如果成功認證,它會提供以下憑據:

  • request.user will be a Django User instance.
  • request.auth will be None.

未認證時返回401,帶一個WWW-Authenticate header。比如:

WWW-Authenticate: Basic realm="api"

TokenAuthentication

單單使用一個token-based HTTP認證方案。

首先需要在認證類設置中包含TokenAuthentication

此外在INSTALLED_APPS 設置中包含rest_framework.authtoken

INSTALLED_APPS = (
    ...
    'rest_framework.authtoken'
)

  

然后要同步數據庫,因為rest_framework.authtoken會提供 Django database migrations.

[root@webmaster mofangsvr]# python3.7 manage.py showmigrations

authtoken
 [ ] 0001_initial
 [ ] 0002_auto_20160226_1747
cmdb
 [X] 0001_initial
#有個authtoken的app,有兩個migrations沒有同步


python3.7 manage.py migrate authtoken
#同步數據

  

然后要創建url

from rest_framework.authtoken import views
urlpatterns += [
    path('api-token-auth/', views.obtain_auth_token)
]
#在項目urls.py中加入就行

  

token測試

# curl -X POST -H "Content-Type:application/json" -d '{"username":"yueju_view","password":"123@abAB"}' http://192.168.10.10:8001/api-token-auth/
{"token":"e3205a50505096dacb3fbbadc7de79cd95b3af45"}
#服務端返回了一個token
#在authtoken_token表中產生了一條數據,和user_id關聯,但會發現沒有過期時間

  

class SvrprocessconfigTestViewSet(viewsets.ModelViewSet):


    serializer_class = SvrprocessconfigSerializer
    permission_classes = (IsAuthenticated,)
#在一個類視圖中使用認證權限

  

curl -X GET http://192.168.10.10:8001/cmdb/svrprocess_Test/
{"detail":"身份認證信息未提供。"}
#這時無法訪問,后台401認證錯誤

  

curl -X GET http://192.168.10.10:8001/cmdb/svrprocess_Test/ -H 'Authorization: Token e3205a50505096dacb3fbbadc7de79cd95b3af45'
#帶上token,則成功返回數據

  

JWT認證

http://getblimp.github.io/django-rest-framework-jwt/

測試方式和token的一樣,唯一不一樣的就是token串變得長了幾倍,然后內容每次都是不一樣的。

去查源碼,可以發現是因為在串里加入了時間再進行加密。

過期時間

JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=20),
}
#jwt設置的默認過期時間是300s,可在項目settings中調整
#如果過期,則token不再生效。報以下錯誤

{"detail":"Signature has expired."}

  

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM