DRF认证组件使用流程

如何对已经登录成功的用户实现访问授权,也就是说,只有登录过的用户(有token值)才能访问特定的数据,该DRF的认证组件出场了。

DRF认证组件的使用方式

首先创建认证类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 自定义auth认证
class UserAuth:
def authenticate_header(self, request):
pass
def authenticate(self, request):
try:
# 获取用户请求携带的token
token = request.GET.get('token')
# 查询数据表中是否存在该token
token_obj = UserTokenModel.objects.filter(token=token).first()
if token_obj is not None:
# 如果查询到数据表中查询到该token则返回此token和与此token对应的用户姓名
return token_obj.user.name, token
else:
raise APIException('Token无效')
except Exception as err:
raise APIException(err)

其次在需认证接口中指定认证类

1
2
3
4
5
6
# 书籍列表
class BooksView(ModelViewSet):
# 设置queryset和自定义序列化类,及认证类
queryset = BookModel.objects.all()
serializer_class = BookSerialize
authentication_classes = [UserAuth]

DRF全局认证组件的使用方式

创建自定义认证类

该类位置为:app.untils.authentication.UserAuth,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# DRF认证组件之自定义认证类

# DRF认证类基类
from rest_framework.authentication import BaseAuthentication
# DRF异常接口
from rest_framework.exceptions import APIException

# 引入token表模型
from app.models import UserToken as UserTokenModel

# token认证类
class UserAuth(BaseAuthentication):
def authenticate(self, request):
try:
# 获取用户携带的token
token = request.GET.get('token')
# 获取token对象
token_obj = UserTokenModel.objects.filter(token=token).first()
# 判断是否能获取到token对象,存在返回对应用户对象及token,否则直接抛出异常
if token_obj is not None:
return token_obj.user, token
raise APIException('token无效')
except Exception:
raise APIException('认证失败')

修改setting文件

setting中添加以下代码,多个认证类在DEFAULT_AUTHENTICATION_CLASSES列表中依次添加,且多个认证类如需返回数据只能在最后一个认证类中返回,否则后面的认证类将不再执行。

1
2
3
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES' : ['app.untils.authentication.UserAuth']
}

最后整个views代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# DRF token认证组件
from django.http import JsonResponse

from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
# from rest_framework.exceptions import APIException

# 引入用户模型
from app.models import User as UserModel
from app.models import UserToken as UserTokenModel
from app.models import Book as BookModel
from app.untils import get_token
# 引入自定义序列化类
from app.api_serialize import BookSerialize

# 自定义auth认证,该类提出到app.untils.authentication.UserAuth,故此处注释
# class UserAuth:
# def authenticate_header(self, request):
# pass
# def authenticate(self, request):
# try:
# # 获取用户请求携带的token
# token = request.GET.get('token')
# # 查询数据表中是否存在该token
# token_obj = UserTokenModel.objects.filter(token=token).first()
# if token_obj is not None:
# # 如果查询到数据表中查询到该token则返回此token和与此token对应的用户姓名
# return token_obj.user.name, token
# else:
# raise APIException('Token无效')
# except Exception as err:
# raise APIException(err)

# 用户登录
class UserView(APIView):
def post(self, request):
# 定义一个返回字典
response = dict()
# 定义一个接收数据字典
recev_data = {'username', 'password'}
# 判断用户发送的post数据是否是要接受数据的子集,即用户发送的字段是否符合包含要接受的字段
if recev_data.issubset(set(request.data)):
# 接收用户发送符合要求的数据
userInfo = dict()
for item in recev_data:
userInfo[item] = request.data.get(item)
# 查询是否有该用户
user_obj = UserModel.objects.filter(**userInfo).first()
# 判断用户名密码是否正确
if user_obj:
# 生成access_token
access_token = get_token.generater_token()
# 将生成的access_token写入数据表
UserTokenModel.objects.update_or_create(user=user_obj, defaults={
'token':access_token
})
response['status_code'] = 200
response['status_message'] = '恭喜你,登录成功'
response['access_token'] = access_token
response['user_role'] = user_obj.get_level_display()
else:
response['status_code'] = 201
response['status_message'] = '用户名或密码错误'
return JsonResponse(response)

# 书籍列表
class BooksView(ModelViewSet):
# 设置queryset和自定义序列化类
queryset = BookModel.objects.all()
serializer_class = BookSerialize
# setting中已注册全局认证,此处注释
# authentication_classes = [UserAuth]