Django REST framework - 認證
阿新 • • 發佈:2019-02-04
憑據 設置 except token time 嘗試 failed Coding 身份驗證
目錄
- 認證
- DRF 5種驗證方式
- 如何確定身份驗證?
- 設置身份驗證方案
- 案例: 基於自定義Token認證
- 第一步: 定義一個用戶表和一個保存用戶Token的表
- 第二步: 定義一個登陸視圖
- 第三步定義一個認證類
- 第四步: 使用認證類
認證
(我是誰?)
身份認證是將傳入請求與一組標識憑據相關聯的機制,然後,權限和限制策略可以使用這些憑據來確定是否應該允許該請求.
REST框架提供了許多開箱即用的身份驗證方案,還允許您實現自定義方案。
身份驗證始終在視圖的最開始,在發生權限和限制檢查之前,以及允許任何其他代碼繼續之前運行。
該 request.user
屬性通常將設置為contrib.auth
包User
類的實例。
該 request.auth
屬性用於任何其他身份驗證信息,例如,它可用於表示請求已簽名的身份驗證令牌。
DRF 5種驗證方式
# 基於用戶名和密碼的認證 class BasicAuthentication(BaseAuthentication): pass # 基於Session的認證 class SessionAuthentication(BaseAuthentication): pass # 基於Tokend的認證 class TokenAuthentication(BaseAuthentication): pass # 基於遠端用戶的認證(專用用戶管理服務器) class TokenAuthentication(BaseAuthentication): pass
如何確定身份驗證?
身份驗證方案始終定義為類列表。REST框架將嘗試對列表中的每個類進行身份驗證,並將設置request.user和request.auth使用成功進行身份驗證的第一個類的返回值。
如果沒有類進行身份驗證,request.user則將設置為實例django.contrib.auth.models.AnonymousUser,request.auth並將其設置為None。
的價值request.user和request.auth對身份認證的請求可以通過修改UNAUTHENTICATED_USER和UNAUTHENTICATED_TOKEN設置。
設置身份驗證方案
可以使用該
DEFAULT_AUTHENTICATION_CLASSES
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.SessionAuthentication', ) }
您還可以使用
APIView
基於類的視圖在每個視圖或每個視圖集的基礎上設置身份驗證方案。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)
或者,如果您正在使用
@api_view
具有基於功能的視圖的裝飾器。@api_view(['GET']) @authentication_classes((SessionAuthentication, BasicAuthentication)) @permission_classes((IsAuthenticated,)) def example_view(request, format=None): content = { 'user': unicode(request.user), # `django.contrib.auth.User` instance. 'auth': unicode(request.auth), # None } return Response(content)
案例: 基於自定義Token認證
第一步: 定義一個用戶表和一個保存用戶Token的表
class UserInfo(models.Model):
username = models.CharField(max_length=16)
password = models.CharField(max_length=32)
type = models.SmallIntegerField(
choices=((0, '普通用戶'), (1, 'VIP用戶')),
default=0
)
class Token(models.Model):
user = models.OneToOneField(to='UserInfo')
token_code = models.CharField(max_length=128)
第二步: 定義一個登陸視圖
from rest_framework.views import APIView
from app2 import models
from rest_framework.response import Response
import hashlib, time
def get_random_token(username):
"""
根據用戶名和時間戳生成隨機token
"""
timestamp = str(time.time())
m = hashlib.md5(bytes(username, encoding="utf-8"))
m.update(bytes(timestamp, encoding="utf-8"))
return m.hexdigest()
class LoginView(APIView):
"""
校驗用戶名是否正確從而生成token的視圖
"""
def post(self, request):
res = {"code": 0}
# print(request.data)
username = request.data.get("username")
password = request.data.get("password")
user = models.UserInfo.objects.filter(username=username, password=password).first()
if user:
token = get_random_token(username)
models.Token.objects.update_or_create(defaults={"token_code": token}, user=user)
res["token"] = token
else:
res["code"] = 1
res["error"] = "用戶名或密碼錯誤"
return Response(res)
第三步定義一個認證類
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from app2 import models
class MyAuth(BaseAuthentication):
def authenticate(self, request):
# if request.method in ["POST", "PUT", "DELETE"]:
# 如果在表單中需要判斷請求方式 由於表單是post請求,所以獲取token 的方式為 request.data.get("token")
# request.query_params為url中的參數
request_token = request.query_params.get("token", None)
if not request_token:
raise AuthenticationFailed('q.缺少token')
token_obj = models.Token.objects.filter(token_code=request_token).first()
if not token_obj:
raise AuthenticationFailed("無效的Token")
# token_obj.user 通過token這張表的對象和user這個關聯字段 找到 UserInfo表的對象及當前用戶對象
return token_obj.user, request_token
# else:
# return None, None
第四步: 使用認證類
視圖級別認證
# (用的不多)
class CommentViewSet(ModelViewSet):
queryset = models.Comment.objects.all()
serializer_class = app01_serializers.CommentSerializer
authentication_classes = [MyAuth, ]
全局級別認證
# 在settings.py中配置
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.MyAuth", ]
}
Django REST framework - 認證