我正在写我的第一个DRF项目,我对如何实现内置DRF权限类很感兴趣-例如IsAuthenticated
和IsAdminUser
。
在rest_framework/permissions.py
中,您可以找到以下代码:
class IsAdminUser(BasePermission):
...
def has_permission(self, request, view):
return bool(request.user and request.user.is_staff)
class IsAuthenticated(BasePermission):
...
def has_permission(self, request, view):
return bool(request.user and request.user.is_authenticated)
可以看到,两个类都在第二个条件之前检查request.user
。这可能是出于某种原因,但我不知道为什么。
我想到的第一件事是request.user
对象可能有None
值或有一些没有is_staff
或is_authenticated
属性的对象,在这种情况下,request.user.is_staff
和request.user.is_authenticated
将导致AttributeError
。我尝试了一下,即使我发送未经身份验证的请求,request.user
指向AnonymousUser
。同样的东西也写在docs中:
如果没有类认证,请求。的实例django.contrib.auth.models。匿名用户和请求。Auth将被设置没有。
但是这里最有趣的是AnonymousUser
对象实际上有is_staff
和is_authenticated
属性!两者都准备好了False
。那么,为什么要先检查request.user
而不是直接检查request.user.is_staff
和request.user.is_authenticated
条件呢?
request.user
是触发django-rest-framework中所有认证逻辑的一种方式。这是一个延迟属性,必须在request.user.is_authenticated
等属性可用之前访问。
django-rest-framework中的相关代码:
class Request:
…
@property
def user(self):
"""
Returns the user associated with the current request, as authenticated
by the authentication classes provided to the request.
"""
if not hasattr(self, '_user'):
with wrap_attributeerrors():
self._authenticate()
return self._user
正如您所看到的,访问该属性会触发所有的身份验证逻辑,这是下面的权限检查工作所需要的。