rest_framework 遇到`403`forbidden

2020-03-16  本文已影响0人  eeert2

rest_framework默认是对所有的视图函数进行了csrf_exempt认证豁免。

如果你使用了postman等工具测试会发现确实是这样,但是在实际的使用过程中,我们在发送post,update,patch,delete请求时依然会收到403 Forbidden 权限限制。

一、为什么会遇到这种情况

查看APIViewas_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)

二、如何解决

1.推荐的做法,获取并携带csrf-token
2.使用自己的Authentication认证类,覆盖SessionAuthentication认证。
上一篇下一篇

猜你喜欢

热点阅读