目錄django
(我是誰?)api
身份認證是將傳入請求與一組標識憑據相關聯的機制,而後,權限和限制策略可使用這些憑據來肯定是否應該容許該請求.服務器
REST框架提供了許多開箱即用的身份驗證方案,還容許您實現自定義方案。
身份驗證始終在視圖的最開始,在發生權限和限制檢查以前,以及容許任何其餘代碼繼續以前運行。app
該 request.user
屬性一般將設置爲contrib.auth
包User
類的實例。框架
該 request.auth
屬性用於任何其餘身份驗證信息,例如,它可用於表示請求已簽名的身份驗證令牌。dom
# 基於用戶名和密碼的認證 class BasicAuthentication(BaseAuthentication): pass # 基於Session的認證 class SessionAuthentication(BaseAuthentication): pass # 基於Tokend的認證 class TokenAuthentication(BaseAuthentication): pass # 基於遠端用戶的認證(專用用戶管理服務器) class TokenAuthentication(BaseAuthentication): pass
身份驗證方案始終定義爲類列表。REST框架將嘗試對列表中的每一個類進行身份驗證,並將設置request.user和request.auth使用成功進行身份驗證的第一個類的返回值。post
若是沒有類進行身份驗證,request.user則將設置爲實例django.contrib.auth.models.AnonymousUser,request.auth並將其設置爲None。url
的價值request.user和request.auth對身份認證的請求能夠經過修改UNAUTHENTICATED_USER和UNAUTHENTICATED_TOKEN設置。rest
可使用該DEFAULT_AUTHENTICATION_CLASSES
設置全局設置默認認證方案。例如code
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)
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", ] }