Django rest framework 之认证
一、基于token进行用户认证
1、url
from django.conf.urls import url from api.apiview import apiview
urlpatterns = [
url(r'^(?P<version>[v1|v2]+)/login_api/$', apiview.Login.as_view()),
]
2、models
创建两张表,一个存用户信息,一个存用户登录后的token
from django.db import models class user_info(models.Model): username = models.CharField(max_length=32,unique=True,verbose_name='用户名') password = models.CharField(max_length=32,verbose_name='密码') nickname = models.CharField(max_length=32,verbose_name='昵称') class UserToken(models.Model): time = models.DateTimeField(auto_now=True) user = models.OneToOneField(to='user_info',on_delete=None) token = models.CharField(max_length=64)
3、views
apiview.py
from django.shortcuts import HttpResponse from utils.response import BaseResponsefrom api import models import json import time class Login(object): def post(self,request,*args,**kwargs): response = BaseResponse() try: user = request._request.POST.get('username') pwd = request._request.POST.get('password') obj = models.UserInfo.objects.filter(username=user,password=pwd).first() if not obj: response.code = 400000 response.error = {
'username':'用户名或密码错误'
}
response.message = '参数错误' return HttpResponse(json.dumps(response.__dict__)) token_obj = Token() token = token_obj.CreateToken(user) models.UserToken.objects.update_or_create(user=user,defaults={'token':token,'time':time.time()}) response.data = { 'token':token, 'username':user, 'password':pwd } except Exception as e: response.error = str(e) response.code = 400001 response.message = '请求异常' return HttpResponse(json.dumps(response.__dict__))
token.py
from web import models import time from datetime import datetime import hashlib class Token(object): def CreateToken(self,user): ''' 创建token username + 时间戳 转换为md5 :param user: :return: ''' ctime = str(time.time()) token = hashlib.md5(bytes(user, encoding='utf-8')) token.update(bytes(ctime, encoding='utf-8')) return token.hexdigest()
response.py
class BaseResponse(object): def __init__(self): self.message = 'OK!' self.data = None self.error = None self.code = 200
使用postman进行测试
如果用户名和密码正确,会生成token,下次登录时,token的值会更新

当用户名密码错误时,抛出异常

二、使用 Django rest framework认证组件
1.settings
先将rest_framework添加到settings的app里
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'api', #我自己注册的APP 'rest_framework', #添加restframework ]
2.url
from django.conf.urls import url from api.apiview import apiview urlpatterns = [ url(r'^(?P<version>[v1|v2]+)/login_api/$', apiview.Login.as_view()),
url(r'^(?P<version>[v1|v2]+)/userinfo/$', apiview.UserInfo.as_view()), ]
3.views
apiviews.py
from django.shortcuts import HttpResponse from utils.response import BaseResponse from api import models from rest_framework.authentication import BaseAuthentication from rest_framework import exceptions from rest_framework.views import APIView import json import time class MyAuthenticate(BaseAuthentication): # 添加自己的认证逻辑,基类BaseAuthentication中有两个必须要重写的接口 def authenticate(self, request): token = request._request.GET.get('token') # 获取token参数 token_obj = models.UserToken.objects.filter(token=token).first() # 在UserToken表中找到对应的对象 if not token_obj: #如果没有,抛出异常 raise exceptions.AuthenticationFailed('用户认证失败') return (token_obj.user, token_obj) # 将这两个对象分别给request.user,request.auth def authenticate_header(self, request): # 返回相应头信息 pass class UserInfo(APIView): authentication_classes = [MyAuthenticate] #添加局部验证 def get(self, request, *args, **kwargs): response = BaseResponse() try: value_list = ['username','password','nickname'] users = models.user_info.objects.values(*value_list) result = list(users) response.data = { 'users':result } except Exception as e: response.error = str(e) response.code = 400001 response.message = '请求异常' return HttpResponse(json.dumps(response.__dict__))
使用Postman进行测试

三、认证组件源码分析
1.当请求进入路由时,进行的一系列操作
(1)路由匹配时,执行类的as_view方法

(2)然后找到APIView中的as_view方法,然后发现他执行了父类的as_view方法

(3)接着找到View中的as_view方法,发现他执行dispatch方法,接着去子类APIView中找到dispatch方法

(4)在dispatch方法中,首先对request进行封装、认证还有通过反射执行不同的方法

2.封装request
(1)我们进入initialize_request(),发现对原生request和认证类等进行封装

(2)进入get_authenticators后,发现是一个列表生成式

(3)进入authentication_classes,可以看到authentication_classes字段,这个字段默认去配置文件中获取


浙公网安备 33010602011771号