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)