一、基於Token進行用戶認證
創建相應數據庫
class member_type(models.Model):
mtype = models.CharField(max_length=50)
def __unicode__(self):
return self.mtype
class member(models.Model):
username = models.CharField(max_length=30)
password = models.CharField(max_length=100)
email = models.EmailField()
user_type = models.ForeignKey("member_type")
def __unicode__(self):
return self.username
class member_token(models.Model):
user = models.OneToOneField(to=member)
token = models.CharField(max_length=64)
def __unicode__(self):
return self.token


配置路由
from abyss import views
from django.conf.urls import url
urlpatterns = [
url(r'^api/v1/auth$', views.AuthView.as_view(),name='auth'),
url(r'^api/v1/order$', views.OrderView.as_view(),name='order'),
]
在setting文件中,添加rest framework應用
INSTALLED_APPS = [
'rest_framework',
]
配置視圖認證
from rest_framework.views import APIView
from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions
from django.http import JsonResponse
from django.shortcuts import HttpResponse
import hashlib
import time
class Myauthentication(BaseAuthentication):
'''認證類'''
def authenticate(self, request):
token = request._request.GET.get("token")
token_obj = models.member_token.objects.filter(token=token).first()
if not token_obj:
raise exceptions.AuthenticationFailed('用戶認證失敗')
return (token_obj.user, token_obj) # 這里返回值一次給request.user,request.auth
def authenticate_header(self, request):
pass
def make_token(user):
ctime = str(time.time())
hash=hashlib.md5(user.encode("utf-8"))
hash.update(ctime.encode("utf-8"))
return hash.hexdigest()
class AuthView(APIView):
"""登錄認證"""
def dispatch(self, request, *args, **kwargs):
return super(AuthView,self).dispatch(request,*args, **kwargs)
def get(self,request, *args, **kwargs):
return HttpResponse('get is ok')
def post(self,request, *args, **kwargs):
ret={'code':1000,'msg':"登錄成功",'token':None}
try:
user = request._request.POST.get("username")
pwd = request._request.POST.get("password")
obj = models.member.objects.filter(username=user,password=pwd).first()
if not obj:
ret['code'] = 1001
ret['msg'] = "用戶名或密碼錯誤"
else:
token = make_token(user)
models.member_token.objects.update_or_create(user=obj,defaults={"token":token})
ret['token'] = token
except exceptions as e:
ret['code'] = 1002
ret['msg'] = "請求異常"
return JsonResponse(ret)
class OrderView(APIView):
"""查看訂單信息"""
authentication_classes = [Myauthentication,] #添加認證
def get(self, request, *args, **kwargs):
# request.user
# request.auth
ret = {'code': 1003, 'msg': "你的訂單已經完成", 'data': "買了一個媳婦"}
return JsonResponse(ret, safe=True)
登錄認證,登錄后會生成token值

使用token進行訂單查詢:

二、全局自定義認證
通過對Django rest framework認證的源碼分析知道,可以直接在項目的settings.py配置文件中引入自定義的認證類,即可以對所有的url進行用戶認證流程
在應用app目錄下創建utils包,在utils包下創建auth.py文件,內容為自定義的認證類
from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions
from abyss import models
class Myauthentication(BaseAuthentication):
'''認證類'''
def authenticate(self, request):
token = request._request.GET.get("token")
token_obj = models.member_token.objects.filter(token=token).first()
if not token_obj:
raise exceptions.AuthenticationFailed('用戶認證失敗')
# restframework會將元組賦值給request,以供后面使用
return (token_obj.user, token_obj) # 這里返回值一次給request.user,request.auth
def authenticate_header(self, request):
pass
settings.py中的REST_FRAMEWORK作為key作為配置,所以全局配置示例:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES':['abyss.utils.auth.Myauthentication',]
}
#其中寫認證的類的路徑,不要在views中,這里我放在了utils目錄下auth.py中
此外,因為開啟了全局認證,所以每個接口視圖中:authentication_classes = [Myauthentication,] 就不需要設置了。
局部某個視圖不需要認證情況,如認證AuthView應該是可以直接訪問的,那就如下設置:
authentication_classes = [] #authentication_classes為空,代表不需要認證
三、配置匿名用戶
匿名用戶配置
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES":['API.utils.auth.Authentication',],
#其中寫認證的類的路徑,不要在views中,這里我放在了utils目錄下auth.py中
"UNAUTHENTICATED_USER": lambda:"匿名",
#匿名用戶配置,只需要函數或類的對應的返回值,對應request.user="匿名"
"UNAUTHENTICATED_token": None,
#匿名token,只需要函數或類的對應的返回值,對應request.auth=None
}
四、Django rest framework內置的認證類
1.BaseAuthentication
BaseAuthentication是django rest framework為我們提供了最基本的認證類,正如源碼流程一樣,該類中其中定義的兩個方法authenticate和authenticate_header(認證失敗返回的響應頭),使用時候重寫該兩個方法進行認證,正如示例:
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
其它認證類:
##路徑:rest_framework.authentication BasicAuthentication #基於瀏覽器進行認證,瀏覽器彈框 SessionAuthentication #基於django的session進行認證 RemoteUserAuthentication #基於django admin中的用戶進行認證,這也是官網的示例 TokenAuthentication #基於drf內部的token認證
五、總結
1.自定義認證類:
繼承BaseAuthentication,重寫authenticate方法和authenticate_header(pass就可以),authenticate()方法需要有三種情況(返回元祖、出現異常、返回none)。
2.認證配置:
#全局認證
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES":['API.utils.auth.Authentication',]
}
#局部認證
authentication_classes = [BaseAuthentication,]
#是某個視圖不進行認證
authentication_classes =[]
