这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战
一、简单认证示例
场景:用户查看自己购买的订单,需登陆验证
以下是demo:
models.py
from django.db import models
class UserInfo(models.Model):
user_type_choice = (
(1,"普通用户"),
(2,"会员"),
)
user_type = models.IntegerField(choices=user_type_choice)
username = models.CharField(max_length=32,unique=True)
password = models.CharField(max_length=64)
class UserToken(models.Model):
user = models.OneToOneField(to=UserInfo)
token = models.CharField(max_length=64)
认证url(urls.py)
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^api/v1/auth', views.AuthView.as_view()),
url(r'^api/v1/order', views.OrderView.as_view()),
]
views.py
from django.shortcuts import HttpResponse
from django.http import JsonResponse
from rest_framework.views import APIView
from rest_framework.authentication import BaseAuthentication
from . import models
from rest_framework import exceptions
import hashlib
import time
class Authentication(BaseAuthentication):
"""
认证类
"""def authenticate(self, request):
token = request._request.GET.get("token")
toke_obj = models.UserToken.objects.filter(token=token).first()
if not toke_obj:
raise exceptions.AuthenticationFailed("用户认证失败")
return (toke_obj.user, toke_obj) # 这里返回值一次给request.user,request.authdef authenticate_header(self, val):
passdef md5(user):
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 dispatch(self, request, *args, **kwargs):
return super(AuthView, self).dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
return HttpResponse('get')
def post(self, request, *args, **kwargs):
ret = {'code': 1000, 'msg': "登录成功"}
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:
ret['code'] = 1001
ret['msg'] = "用户名或密码错误"else:
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 = [Authentication,] #添加认证def get(self,request,*args,**kwargs):
#request.user#request.auth
ret = {'code':1000,'msg':"你的订单已经完成",'data':"买了一个mac"}
return JsonResponse(ret,safe=True)
用户使用token访问,不带token或token错误会认证错误。
http://127.0.0.1:8000/api/v1/order?token=63743076dfaefa632f6acb302cf90400
###返回结果
{"code": 1000, "msg": "\u4f60\u7684\u8ba2\u5355\u5df2\u7ecf\u5b8c\u6210", "data": "\u4e70\u4e86\u4e00\u4e2amac"}
对于以上demo可能会有疑问为什么添加了authentication_classes认证类列表就会使用我们自己定义的认证类,后续会从源码角度分析原因。