React 和 Django - 警告:django.request:禁止:/api/user - SessionAuthentication

问题描述 投票:0回答:1

我创建了这个 Django 和 React 项目(https://github.com/axilaris/docker-django-react-celery-redis),并且我在使用 SessionAuthentication 访问 API 时遇到困难。您可以轻松地测试并剥离我的代码:

  • docker-compose 构建
  • docker-compose up

我在访问 /api/user 时不断遇到访问问题(您可以通过注册、登录进行测试)

backend_container   | Forbidden: /api/user
backend_container   | WARNING:django.request:Forbidden: /api/user

您可以在这里查看更多日志: https://gist.github.com/axilaris/7b7a5c50f4f7112b440eaf8ef8100d9d

In my django api code (backend/user_api/views.py):

    class UserView(APIView):
        permission_classes = (permissions.IsAuthenticated,)
        authentication_classes = (SessionAuthentication,)
        def get(self, request):
            serializer = UserSerializer(request.user)
            return Response({'user': serializer.data}, status=status.HTTP_200_OK)



In settings.py:

CORS_ALLOWED_ORIGINS = [
    'http://localhost',
    'http://127.0.0.1',
    'http://0.0.0.0',
]

CORS_ALLOW_CREDENTIALS = True

INSTALLED_APPS = [
..
    'corsheaders',
]


MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
...
]

and in react:
axios.defaults.xsrfCookieName = 'csrftoken';
axios.defaults.xsrfHeaderName = 'X-CSRFToken';
axios.defaults.withCredentials = true;

  useEffect(() => {
    client.get("/api/user")
    .then(function(res) {
      setCurrentUser(true);
    })
    .catch(function(error) {
      setCurrentUser(false);
    });
  }, []);

这是我的网络日志:https://gist.github.com/axilaris/f5076f8a1e009d77df78de562259427e

/api/login 确实提供了 csrftoken 和 sessionid cookie。但是这个cookie没有在/api/user中使用

为什么每当我登录并在浏览器上重新加载回本地主机后,它就会禁止 /api/user 并返回到登录页面。我觉得 CORS 设置正确,并且后端和前端的凭据都设置为 true。

来自 ChatGPT 的更新(询问如何使其与 HttpOnly 一起工作):

If you can't access the session cookie from the client-side, it's probably because the cookie has the HttpOnly flag set. This is a security feature that prevents JavaScript from accessing the cookie, helping mitigate cross-site scripting attacks.
reactjs django django-rest-framework cors httponly
1个回答
0
投票

你有:

Client (React) --> [HTTP Request with CSRF Token] --> Django Backend
                                                  /\
                                                  |
                                                  +--- [Session Authentication & CSRF Validation]

为了使

SessionAuthentication
正常工作,请确保正确设置 Django 的会话 cookie (
sessionid
) 和 CSRF 令牌 cookie (
csrftoken
) 并将其发送到客户端。通常应在
HttpOnly
cookie 上设置
sessionid
标志以增强安全性,如此线程中所述。

由于会话 cookie (

sessionid
) 应该是
HttpOnly
,React 应用程序不会直接与其交互。相反,请确保
axios
配置正确包含每个请求的凭据。该部分似乎在您的设置中配置正确(
axios.defaults.withCredentials
设置为
true
)。

settings.py
应包括:

SESSION_COOKIE_HTTPONLY = True  # Default value is True, which is recommended
SESSION_COOKIE_SAMESITE = 'Lax' # Consider 'None' if strictly necessary and secure is set
SESSION_COOKIE_SECURE = True    # Set to True if you are using HTTPS

对于 CSRF cookie 配置:

CSRF_COOKIE_HTTPONLY = False    # Should generally be False to allow JavaScript to read the value
CSRF_COOKIE_SECURE = True       # Set to True if you are using HTTPS

CSRF_COOKIE_HTTPONLY
设置为
False
会使您的应用程序更容易受到 XSS 攻击,因为它允许 JavaScript 访问 CSRF cookie。更好的方法是保留 CSRF 令牌
HttpOnly
,并从旨在显式返回 CSRF 令牌的单独 API 端点获取它,或者将 CSRF 令牌包含在页面正文中并让 JavaScript 从那里读取它。

尽管...自 2016 年以来记录在

django/django
PR 7700commit c27104a

将 CSRF cookie 指定为

HttpOnly
并不能提供任何实际保护,因为 CSRF 仅用于防止跨域攻击。如果攻击者可以通过 JavaScript 读取 cookie,那么就浏览器所知,他们已经位于同一个域中,因此他们无论如何都可以做任何他们喜欢做的事情。 (XSS 是一个比 CSRF 大得多的漏洞。)

使 JavaScript 可以访问 CSRF 令牌时要考虑的主要风险是 XSS——跨站点脚本 。如果您的应用程序容易受到 XSS 攻击,攻击者可以利用此漏洞完全绕过 CSRF 保护。因此,任何向 JavaScript 公开 CSRF 令牌的决定都应该伴随严格的 XSS 缓解策略。例如,请参阅 StackHawk 中的“Django XSS:示例和预防”。

测试登录时获取CSRF token和session cookie的流程。验证来自 React 的后续请求是否自动在标头和会话 cookie 中包含 CSRF 令牌(即使 JavaScript 由于

sessionid
标志而无法读取
HttpOnly
cookie)。

© www.soinside.com 2019 - 2024. All rights reserved.