【问题标题】:Django/Graphene/Apollo/django-webpack-loader/Vue: CORS/CSRF not working together?Django/Graphene/Apollo/django-webpack-loader/Vue:CORS/CSRF 不能一起工作?
【发布时间】:2019-10-08 00:58:53
【问题描述】:

我正在做一个项目,使用 Django 作为后端,Vue 作为前端,并尝试实现 Apollo/Graphene/GraphQL 作为数据传输层。 大部分都有效,但我不了解 CORS/CSRF 设置。

(在这里进行了大量研究。hereherehere

有谁知道如何通过 CSRF 令牌解决保护 graphql/graphene API 的问题?在 django 日志终端上,我得到:

Forbidden (CSRF token missing or incorrect.): /graphql/

...在 Vue/Js 控制台上我看到了

Cross-Origin Request Blocked: The Same Origin Policy disallows 
reading the remote resource at http://localhost:8080/sockjs-node/
info?t=1558447812102. 

你可以看到(并结帐,它是开源的)这个项目here

http://localhost:8000http://localhost:8000/adminhttp://localhost:8000/ 工作得很好。查询 query{menuItems{id, title, slug, disabled}} 在 graphiql 中运行良好。

settings.py:


INSTALLED_APPS = [
    # ...
    'corsheaders',
    'rest_framework',
    'webpack_loader',
    'graphene_django',
]

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

CORS_ORIGIN_ALLOW_ALL = DEBUG    # (=True)

问题出在: * yarn servehttp://localhost:8080 上运行 * ./manage.py runserverhttp://localhost:8000 上运行,并通过 webpack 代理 Vue 前端开发服务器。

vue.config.js:


module.exports = {
    // The base URL your application bundle will be deployed at
    publicPath: 'http://localhost:8080',

    // ...

    chainWebpack: config => {
        // ...
        config.devServer
            .public('http://localhost:8080')
// ...

vue-apollo.js:

const httpEndpoint = process.env.VUE_APP_GRAPHQL_HTTP || 'http://localhost:8000/graphql/'

编辑:如果我用csrf_exempt 包装graphql/ api urlpath,它可以工作:

urlpatterns = [ # ...
    path('graphql/', csrf_exempt(GraphQLView.as_view(graphiql=True, schema=schema))),
]

但这在安全方面是 BadIdea(TM)。如何使用 Vue 与 Django 和 webpack_loader 将该令牌放入前端?

【问题讨论】:

  • 小记:安装应用的顺序很重要。所以也许可以尝试解决这个问题,我相信这不会是一个解决方案,但你永远不能太确定。
  • “有谁知道如何解决这个问题?” 解决什么?你不清楚你遇到了什么实际问题。 “原因是恕我直言,由于 CORS 设置格式不正确,服务器拒绝向外部提供数据。” 您得到什么确切的错误消息来指示“格式错误的 CORS 设置”?必须做些什么来尝试解决这个问题? “但我真的放弃了。” 你放弃了试图解决问题的真正原因?现在您正在寻找解决方法?要不然是啥? “所以可能主要问题是:如何将 CSRF 令牌集成到 graphql api 请求中?” 这与 CORS 问题有什么关系?
  • 解决这个问题的更好方法是从一个域/端口为所有内容提供服务,并使用前端代理将内容路由到两个服务器。我为此推荐 Traefik。
  • (补充一下我昨天的评论,如果您尝试将非标准网络用于 AJAX 或 WS 请求,您可能会陷入公司/移动防火墙的困境。如果您坚持使用 80/443可以,除非您知道您的用户群不会有问题)。
  • @nerdoc...我使用 Axios 和 vue.js 从我的后端收集所需的数据。在这种情况下,有很多关于如何允许传递 CSRF 令牌的帖子,因此 Django 支持您的调用,但或多或​​少您只需设置一个全局默认值以允许它:axios.defaults.xsrfHeaderName = "X-CSRFToken" 然后axios.defaults.xsrfCookieName = 'csrftoken'

标签: django vue.js csrf apollo


【解决方案1】:

跳过对该请求的 CSRF 检查可能没问题,但不能根据您提供的信息对其进行评估,所以让我解释一下为什么我们首先需要 CSRF 检查。

创建 CSRF 是为了修复 HTTP 和 Web 浏览器工作方式中存在的“漏洞”。这个漏洞如下:任何网站都可以包含向您的网站提交数据的 from,这样做时,cookie 将沿着用户提交的表单传递。

这意味着第 3 方网站可以诱骗您的用户在您的网站上执行某些操作。为了防止这种情况,创建了 CSRF 令牌的想法。简而言之:您网站上负责执行任何可能对用户有害的操作的任何表单,当被第 3 方网站欺骗提交它时,必须在为此操作提交的所有数据旁边包含一个 CSRF 令牌字段.相同的 CSRF 令牌需要存在于用户的会话或 cookie 中。提交表单时,会比较这两个令牌,如果它们不匹配或其中任何一个不存在,则表单将被拒绝。

这可以保护由第 3 方网站提交的任何表格,因为来自您网站的 cookie 无法被其他网站读取,即使它们是与来自该网站的请求一起传递的。那么该网站不可能在表单数据中设置匹配令牌。

话虽如此,当您不使用 cookie 保持用户会话时,不会出现此问题。当您的前端位于单独的域中时,这也不是问题,因为来自您的前端的所有请求都将具有带有其域名的 Origin 标头。因此,如果出现上述任何一种情况,您可以相应地禁用 CSRF 检查:

  • 当不使用 cookie 进行用户会话或用户身份验证时(例如,如果您完全依赖标头传递的 JWT),您可以对所有不使用 cookie 的视图完全禁用 CSRF。
  • 当您的前端位于单独的域(或子域)上且 CORS 允许连接到您的网站时,请使用 CSRF_TRUSTED_ORIGINS 将其列入白名单。

【讨论】:

    猜你喜欢
    • 2018-07-20
    • 2019-12-10
    • 2021-06-27
    • 1970-01-01
    • 2021-08-22
    • 2016-09-25
    • 1970-01-01
    • 1970-01-01
    • 2015-10-02
    相关资源
    最近更新 更多