建立相應數據庫python
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應用django
INSTALLED_APPS = [ 'rest_framework', ]
配置視圖認證api
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進行訂單查詢:session
經過對Django rest framework認證的源碼分析知道,能夠直接在項目的settings.py配置文件中引入自定義的認證類,便可以對全部的url進行用戶認證流程app
在應用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中post
此外,由於開啓了全局認證,因此每一個接口視圖中: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 }
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 =[]