文章目录
一、认证(Authentication)
身份认证是将传入的请求与一组标识凭据(例如发送该请求的用户或其签名的token)相关联的机制。然后,“权限”和“限流”可以使用这些凭据来确定是否应允许该请求。
DRF提供了几种开箱即用的身份认证方案,还允许我们自定义认证方案。
DRF内置了几个认证类,如果需要可以参考官方文档:传送门
两个与认证相关的request属性:
-
request.user
属性通常被设置为contrib.auth
包中User
类的一个实例; -
request.auth
属性用于任何其他身份认证信息,例如,它可以用于表示请求签名的身份认证令牌(token)。
1.1 身份认证的流程
身份认证总是在视图的最开始运行,在执行视图其他任何其他代码之前执行。
身份认证方案被定义为一个列表,DRF将尝试使用列表中的每个类进行身份认证,并使用第一个成功身份认证的类的返回值设置request.user
和request.auth
。
如果没有类进行认证,request.user
将被设置成django.contrib.auth.models.AnonymousUser
(django的匿名用户)的实例,request.auth
将被设置成None
。
对于未经身份认证的请求,可以使用UNAUTHENTICATED_USER
和UNAUTHENTICATED_TOKEN
设置修改request.user
和request.auth
的值。
1.2 自定义认证类
要实现自定义的认证类,就要继承BaseAuthentication
类并且重写authenticate(self, request)
方法。如果认证成功,该方法应返回(user, auth)
的二元元组,否则返回None。
在某些情况下,也可以不返回None,而是抛出AuthenticationFailed
异常:
- 如果不尝试认证而返回None,则将继续检查其他任何正在使用的身份认证方案。
- 如果试图进行身份认证但失败,则应该抛出
AuthenticationFailed
异常。这将立即返回一个错误响应,无论是否进行权限检查,也不继续检查其他任何身份认证方案。
通常情况下,我们会在APP文件夹下创建一个py文件,单独存放这些认证类:
from app01 import models
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
class authlogin(BaseAuthentication):
def authenticate(self, request):
token = request.GET.get('token') # 来访问数据的时候需要携带的token
res = models.UserToken.objects.filter(token = token).first() # 如果和数据库的值不一致,不允许访问数据
if res:
return (res.user,token)# 返回元组,第一个值会给request.user ,第二值会给request.auth
else:
raise AuthenticationFailed('您没有登录')
1.3 设置认证方案
-
局部使用:
在视图中设置以下属性,则只会对该视图生效:
class MyView(APIView): # 只对APIView的子类有效 authentication_classes = [认证类, 认证类……] ……
注意:如果列表为空,则说明对视图不进行认证限制,相当于局部禁用认证。
-
全局使用:
在项目配置文件settings.py中,写入以下内容,则会对全部视图生效:
REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": [ "app名称.自建py文件.自定义认证类", …… ] }
注意:如果配置多个认证类,则要把返回元组的类放在最后。
二、权限(Permissions)
确定好用户的身份后,就需要确定具体的用户权限了。权限用来确定用户是否可以对API进行访问,DRF自带了一些权限,并且支持我们自定义权限。
DRF内置权限的详情可以参考官方文档:传送门
2.1 权限检查流程
权限检查始终在视图的身份认证代码之后,其他任何代码之前执行。
与系统认证方案类似,权限也是通过一个列表进行设置,列表中包含的也是一个个的类。
在运行视图主体之前,将检查列表中的每个权限。如果任何权限检查失败,将抛出exceptions.PermissionDenied
或exceptions.NotAuthenticated
异常,并且视图的主体将不会运行。
2.2 对象级别的权限
上面说的是视图级别权限,DRF也支持对象级权限。对象级权限用于确定是否应该允许用户对特定对象进行操作,该对象通常是一个模型实例。
当调用get_object()
方法时,对象级权限由DRF的通用视图(GenericAPIView及其子类)运行。如果不允许用户对给定对象进行操作,则会引发PermissionDenied
异常。
如果想强制执行对象级别的权限检测,或者像重写get_object()
方法。那么需要在检索对象的时候显式调用check_object_permissions(request, obj)
方法。这将抛出PermissionDenied
或NotAuthenticated
异常,或者如果视图有适当的权限就直接返回对象。
比如:
def