rest_framework
默认是对所有的视图函数进行了csrf_exempt
认证豁免。
如果你使用了postman
等工具测试会发现确实是这样,但是在实际的使用过程中,我们在发送post
,update
,patch
,delete
请求时依然会收到403 Forbidden
权限限制。
一、为什么会遇到这种情况
查看APIView
的as_view()
源码,最后一行代码:
# Note: session based authentication is explicitly CSRF validated,
# all other authentication is CSRF exempt.
return csrf_exempt(view)
翻译过来就是:
基于`session`的用户认证明确的要求了`CSRF`认证,其它的用户认证类都进行豁免了。
如果你对rest_framework
的用户认证不熟悉的话,可以看看https://www.jianshu.com/p/2079065de888
在rest_framework.settings
文件中,包含了rest_framework
所有的默认设置,其中关于用户认证类的设置:
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
],
问题就出在SessionAuthentication
中:
SessionAuthentication
只对经过身份验证的用户执行CSRF
检查,只有这样才能避免CSRF
攻击,https://www.jianshu.com/p/3b3264061b26讲述了什么是csrf
攻击。
而对匿名用户,则不进行csrf
验证,这就是为什么使用postman
等工具能够在不携带csrf-token
的情况下进行访问,而在正式环境中确会收到403 Forbidden
class SessionAuthentication(BaseAuthentication):
def authenticate(self, request):
"""
Returns a `User` if the request session currently has a logged in user.
Otherwise returns `None`.
"""
# Get the session-based user from the underlying HttpRequest object
user = getattr(request._request, 'user', None)
# Unauthenticated, CSRF validation not required
if not user or not user.is_active:
return None
# 非匿名用户,则需要进行 CSRF 验证
self.enforce_csrf(request)
# CSRF passed with authenticated user
return (user, None)