問題1:有些 API
須要用戶登陸成功以後才能訪問,有些無需登陸就能訪問python
models.py數據庫
from django.db import models class UerInfo(models.Model): user_type_choices = ( (1, '普通用戶'), (2, 'VIP'), (3, 'SVIP'), ) user_type = models.IntegerField(choices=user_type_choices) username = models.CharField(max_length=32, unique=True) password = models.CharField(max_length=64) class UserToken(models.Model): user = models.OneToOneField(to='UerInfo') token = models.CharField(max_length=64)
urls.pydjango
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^api/v1/auth/$', views.AuthView.as_view()), ]
views.pyapi
from django.http import JsonResponse from rest_framework.views import APIView from api import models def md5(user): import hashlib import time ctime = str(time.time()) m = hashlib.md5(bytes(user, encoding='utf-8')) m.update(bytes(ctime, encoding='utf-8')) return m.hexdigest() class AuthView(APIView): def post(self, request, *args, **kwargs): ret = {'code': 1000, 'msg': None} try: user = request._request.POST.get('username') pwd = request._request.POST.get('password') obj = models.UerInfo.objects.filter(username=user, password=pwd).first() if not obj: ret['code'] = 1001 ret['msg'] = '用戶名或密碼錯誤' # 爲登陸用戶建立token token = md5(user) # 存在就更新, 不存在就建立 models.UserToken.objects.update_or_create(user=obj, defaults={'token': token}) ret['token'] = token except Exception as e: ret['code'] = 1002 ret['msg'] = '請求異常' return JsonResponse(ret)
解決:(認證組件的基本使用)post
urls.pyurl
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^api/v1/auth/$', views.AuthView.as_view()), url(r'^api/v1/order/$', views.OrderView.as_view()), ]
views.pyrest
class Authentication(object): def authenticate(self, request): token = request._request.GET.get('token') token_obj = models.UserToken.objects.filter(token=token).first() if not token_obj: raise exceptions.AuthenticationFailed('用戶認證失敗') # 在rest framework內部會將這兩個字段賦值給request, 以供後續操做使用 return (token_obj.user, token_obj) def authenticate_header(self, request): pass class OrderView(APIView): ''' 訂單相關業務 ''' authentication_classes = [Authentication, ] def get(self, request, *args, **kwargs): token = request._request.GET.get('token') if not token: return HttpResponse('用戶未登陸') ret = {'code': 1000, 'msg': None, 'data': None} try: ret['data'] = ORDER_DICT except Exception as e: pass return JsonResponse(ret)
這樣寫有一個很差之處,在每個業務中,都須要添加 authentication_classes = [Authentication, ]
作相關認證,所以能夠把它設置爲全局code
須要在 settings.py 中添加token
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.auth.FirstAuthentication', 'api.utils.auth.Authentication'] }
在 api 下新建 utlis,utils中新建 auth.pymd5
# -*- coding: utf-8 -*- from rest_framework import exceptions from api import models from rest_framework.authentication import BaseAuthentication class FirstAuthentication(BaseAuthentication): def authenticate(self, request): pass def authenticate_header(self, request): pass class Authentication(BaseAuthentication): def authenticate(self, request): token = request._request.GET.get('token') token_obj = models.UserToken.objects.filter(token=token).first() if not token_obj: raise exceptions.AuthenticationFailed('用戶認證失敗') # 在rest framework內部會將這兩個字段賦值給request, 以供後續操做使用 return (token_obj.user, token_obj) def authenticate_header(self, request): pass
views.py
from django.shortcuts import render, HttpResponse from django.http import JsonResponse from rest_framework.views import APIView from api import models ORDER_DICT = { 1: { 'name': 'qiu', 'age': 18, 'gender': '男', 'content': '...' }, 2: { 'name': 'xi', 'age': 19, 'gender': '男', 'content': '.....' } } def md5(user): import hashlib import time ctime = str(time.time()) m = hashlib.md5(bytes(user, encoding='utf-8')) m.update(bytes(ctime, encoding='utf-8')) return m.hexdigest() class AuthView(APIView): authentication_classes = [] def post(self, request, *args, **kwargs): ret = {'code': 1000, 'msg': None} try: user = request._request.POST.get('username') pwd = request._request.POST.get('password') obj = models.UerInfo.objects.filter(username=user, password=pwd).first() if not obj: ret['code'] = 1001 ret['msg'] = '用戶名或密碼錯誤' # 爲登陸用戶建立token token = md5(user) # 存在就更新, 不存在就建立 models.UserToken.objects.update_or_create(user=obj, defaults={'token': token}) ret['token'] = token except Exception as e: ret['code'] = 1002 ret['msg'] = '請求異常' return JsonResponse(ret) class OrderView(APIView): ''' 訂單相關業務 ''' # authentication_classes = [FirstAuthentication, Authentication, ] def get(self, request, *args, **kwargs): token = request._request.GET.get('token') if not token: return HttpResponse('用戶未登陸') ret = {'code': 1000, 'msg': None, 'data': None} try: ret['data'] = ORDER_DICT except Exception as e: pass return JsonResponse(ret) class UserInfoView(APIView): ''' 用戶中心 ''' def get(self, request, *args, **kwargs): return HttpResponse('用戶信息')
這樣一來,全部的業務都添加了認證,當某一個不須要此認證時,只需將 authentication_classes
設置爲空列表便可
若是是匿名用戶,能夠將其設置爲 None
setting.py
REST_FRAMEWORK = { 'UNAUTHENTICATED_USER': None, # 匿名,request.user = None 'UNAUTHENTICATED_TOKEN': None # 匿名,request.auth = None }