一丶简介
本篇文章主要是通过一个实际的案例来介绍drf的认证组件如何使用
二、代码
在第一节的基础上修改代码
之所以有三个认证组件,是因为访问api接口的时候,携带token有两种方式,第一种是携带字url中,第二种是携带在请求头中,而第三种则是没有认证通过返回错误使用,前两者的return皆为None,根据上一节源码的分析可知,返回值为None则会跳到下一个认证组件,当跳到第三个认证组件时,便报错跳出,下面为代码:
# 路径:ext/auth.py
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from api import models
class QueryParamsAuthentication(BaseAuthentication):
def authenticate(self, request):
# 用户认证步骤:
# 1.读取请求传递的token
# 2.校验合法性
# 3.三种返回值
# 3.1 认证成功,返回元组(11,22) 11,22分别存入request.user和request.auth
# 3.2 认证失败,抛出异常 返回错误信息
# 3.3 返回None(不常用),用于多个认证类
# /xxx/xxx/?token=1231dd
# token = request._request.GET.get('token')
# drf的request源码中的query_params=_request.GET
token = request.query_params.get('token')
if not token:
return
user_object = models.UserInfo.objects.filter(token=token).first()
# 这里获取到请求传递的token后,理应校验合法性,不过这里先略去
if user_object:
# request.user和request.auth
return user_object, token
return
# raise AuthenticationFailed("认证失败")
# 如果返回字符串,字符串会放入detail中,如果返回字典,则该字典会替代detail
def authenticate_header(self, request):
return 'API'
class HeaderAuthentication(BaseAuthentication):
def authenticate(self, request):
# 用户认证步骤:
# 1.读取请求传递的token
# 2.校验合法性
# 3.三种返回值
# 3.1 认证成功,返回元组(11,22) 11,22分别存入request.user和request.auth
# 3.2 认证失败,抛出异常 返回错误信息
# 3.3 返回None(不常用),用于多个认证类
# /xxx/xxx/?token=1231dd
# token = request._request.GET.get('token')
# drf的request源码中的query_params=_request.GET
token = request.META.get('HTTP_AUTHORIZATION')
if not token:
return
user_object = models.UserInfo.objects.filter(token=token).first()
# 这里获取到请求传递的token后,理应校验合法性,不过这里先略去
if user_object:
# request.user和request.auth
return user_object, token
# raise AuthenticationFailed("认证失败")
# 如果返回字符串,字符串会放入detail中,如果返回字典,则该字典会替代detail
return
def authenticate_header(self, request):
return 'API'
class NoAuthentication(BaseAuthentication):
def authenticate(self, request):
raise AuthenticationFailed({"code": 202, "msg": "认证失败"})
def authenticate_header(self, request):
return 'API'
# api/models.py
from django.db import models
class UserInfo(models.Model):
username = models.CharField(verbose_name='用户名', max_length=32)
password = models.CharField(verbose_name='密码', max_length=64)
# 临时方式、jwt
token = models.CharField(verbose_name='TOKEN', max_length=64, null=True, blank=True)
# api/views.py
import uuid
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from api import models
class UserView(APIView):
def get(self, request):
print(request.user)
print(request.auth)
return Response("UserView")
class LoginView(APIView):
authentication_classes = []
def post(self, request):
# 1.接受用户名和密码
print(request.data)
user = request.data.get('username')
pwd = request.data.get('password')
# 2.数据库校验
user_object = models.UserInfo.objects.filter(username=user, password=pwd).first()
if not user_object:
return Response({'code': 201, "msg": "用户名密码错误"})
token = str(uuid.uuid4())
user_object.token = token
user_object.save()
return Response({'code': 0, 'data': token})
class OrderView(APIView):
def get(self, request):
self.dispatch()
return Response("OrderView")
三、测试接口
①访问login接口获取token
②不携带token访问user
③请求头携带token访问user
④url携带token访问user
可见已经实现认证功能