【问题标题】:Forbidden (403) Post Request in a "Build React App" but work fine with React App running on "http://localhost:3000/" and PostMan禁止(403)在“构建 React 应用程序”中发布请求,但可以在“http://localhost:3000/”和 PostMan 上运行的 React 应用程序正常工作
【发布时间】:2021-03-04 16:38:31
【问题描述】:

我正在使用 Django Rest Framework 和 React。当我在“localhost:3000”上运行反应应用程序时,每个发布请求都被接受并且工作正常。但是在我使用“npm run build”构建反应应用程序之后。然后,所有 POST 请求都在"localhost:8000" 上被禁止(403)。但是,"localhost:3000" 上的一切都很好

【问题讨论】:

  • 这可能是 CSRF 令牌...

标签: reactjs django django-rest-framework django-react


【解决方案1】:

Django 有cross-site request forgery (CSRF) protection。在每个表单中,它使用一个包含 csrf 令牌的额外小元素,然后对其进行验证。

您可以使用 JavaScript 函数 specified in the Django documentation 提取 csrf 令牌:

function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
const csrftoken = getCookie('csrftoken');

然后您可以使用以下命令创建fetch

fetch(url, {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      'X-CSRFToken': csrftoken
    },
    body: {
        // …
    }
})

【讨论】:

  • 它对我有用。但我不明白为什么“localhost:8000”中需要 CSRF TokenAuthentication 而“localhost:3000”中不需要。 “localhost:3000”中没有 CSRF Coo​​kie。
【解决方案2】:

可能有很多原因:

# update backend/server/server/settings.py
# ...
INSTALLED_APPS = [
    #...
    'corsheaders', # add it here
    #...
]

# define which origins are allowed
CORS_ALLOWED_ORIGINS = [
    "http://localhost:3000",
    "http://127.0.0.1:3000"
]

# add to middleware
MIDDLEWARE = [
    #...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    #...
]
  • 请在settings.py 中查看ALLOWED_HOSTS
  • 请尝试使用DEBUG=True 运行 Django 服务器并查看有关请求的更多信息,您可以在 Web 浏览器的开发人员工具中查看它
  • 请检查您的请求发送到哪个地址?我正在使用不同的服务器地址进行开发和生产:
import axios from "axios";
if (window.location.origin === "http://localhost:3000") {
  axios.defaults.baseURL = "http://127.0.0.1:8000";
} else {
  axios.defaults.baseURL = window.location.origin;
}

  • 正如 Willem Van Onsem 所写,这可能是 CSRF 的问题,但默认情况下,CSRF 仅针对基于会话的身份验证启用(您使用什么身份验证?)

请看以下文章:

【讨论】:

    猜你喜欢
    • 2020-11-22
    • 1970-01-01
    • 1970-01-01
    • 2014-06-22
    • 2020-07-16
    • 1970-01-01
    • 2020-01-21
    • 2020-12-20
    • 2020-11-21
    相关资源
    最近更新 更多