403 由石墨烯-django 提供。不要使用 csrf_exempt

Posted

技术标签:

【中文标题】403 由石墨烯-django 提供。不要使用 csrf_exempt【英文标题】:403 by graphene-django. don't use csrf_exempt 【发布时间】:2019-01-16 18:25:13 【问题描述】:

我使用graphene-django。创建一个应用程序,GraphiQL 可以很好地用于登录和其他功能。但是当我使用Insomnia 时,我得到了403 Forbidden 错误。

我参考了这个文档, https://github.com/howtographql/howtographql/blob/master/content/backend/graphql-python/4-authentication.md

我试过了:

    使用csrf_exempt;它工作正常,但我当然不会使用它。 使用django-cors-headers;它运作良好。

我该如何解决这个403 错误?

【问题讨论】:

github.com/graphql-python/graphene-django/issues/170 我找到了。你能在生产中使用 csrf_exempt 吗? 为什么我可以使用 csrf_exempt??? 【参考方案1】:

如果您想在 Graphene 中使用 CSRF 中间件,则需要在请求标头的 cookie 中设置 CSRF 令牌。

我没有使用 Insomnia 的经验,但我相信它可以让您自定义请求标头,就像 Apollo 链接一样。

【讨论】:

【参考方案2】:

假设您有 http://127.0.0.1:8000/graphql/ 并使用 JWT。 按照这个截图,也许他们可以帮助你。

【讨论】:

【参考方案3】:

变量。 1) 设置标题X-CSRFToken(也可以试试X-CSRFTOKENcsrftoken

变量。 2)不是很正确的解决方案,但它很容易并且有效! 使用 GET 请求代替 POST。不知何故,它工作...

变量。 3) 不适合我。您可以尝试正确的方式并添加到cookie X-CSRFTOKEN a) 单击 Cookie 选项卡 b) 管理 Cookie 按钮 c) 操作 -> 添加 Cookie 附:实际上 Insomnia 会自动注入 csrftoken,你可以尝试通常的 REST POST,你会看到,它工作正常,并且 insomnia 会自动添加 csrftoken...

【讨论】:

【参考方案4】:

我不推荐 @yestema 的第二种方法来解决您面临的问题。

避免使用GET 方法查询您的 GraphQL 端点

如果一个人想要实现这个变通方法并且还在为mutations 使用 Graphql,那么它看起来就像一个糟糕的设计。

作为标准,GET 请求不得更改服务器或数据库的状态,mutations 在大多数情况下用于更改其中一个或另一个的状态(可能仅数据库,因为您的应用程序应该是无状态的)。

请注意,您也可以使用query 方法来更改后端的状态,但是,这又违反了既定标准,如grapqhl documentation 中所述:

[...] 在 REST 中,任何请求最终都可能对服务器造成一些副作用,但按照惯例,建议不要使用 GET 请求来修改数据。 GraphQL 是类似的——从技术上讲,任何查询都可以实现来导致数据写入。但是,建立一个约定是很有用的,即任何导致写入的操作都应通过突变显式发送。

什么时候可以安全使用 csrf_exempt 装饰器?

为了给想知道摆脱默认 CSRF 检查有多糟糕的人提供提示,这是我的两分钱解释。

当浏览器自动发送身份验证参数时,服务会受到 CSRF 攻击,这是基于会话的默认 Django 身份验证系统的情况。

如果您仅将 Django 应用程序用作 API 后端,则您可能依赖于另一种身份验证机制,例如 DRF's TokenAuthentication 或某种 JWT implementation。

基本上,这些身份验证系统不会受到 CSRF 攻击,因为如果恶意网站想要代表您的用户访问您的服务器(这就是 CSRF 的全部内容),它将无法设置 @987654331 @ 你的服务器期望的 HTTP 标头来实际验证请求(前提是你将令牌安全地存储在一个只能由你的前端应用程序域访问的 cookie 中......)。


tl;dr

继续使用 POST 请求发送您的 GraphQL 查询,这是最佳做法。

如果您的 GraphQL 端点只能由经过身份验证的用户访问,并且您的身份验证系统不依赖 Django 的会话,则可以免除您的端点进行 CSRF 检查。

但是,如果您使用 Django 的默认身份验证系统——即存储在 cookie 中的sessionid,那么您必须强制执行csrf 验证。 此时,您唯一的机会是,如先前的答案所述,在您的 HTTP 请求中添加 X-CSRFToken 标头,并为其提供先前对服务器的请求自动设置的 csrftoken cookie 的值。


我最初在GitHub 上发布了这个答案,但我认为它在这里也很有用。

【讨论】:

【参考方案5】:

您正在寻找的是csrf_exempt 在您的url(r'^graphql', csrf_exempt(GraphQLView.as_view(graphiql=True))),

您可以像这样导入它:from django.views.decorators.csrf import csrf_exempt

GraphQL 端点不需要 csrf 令牌,因为它是一个 API。

默认情况下,生产环境中需要 CSRF 令牌,因为 django 不知道哪个 POST 请求是针对表单的,哪个不是。还 如果您想使用 GraphQL 端点,CSRF 可能会很有用 仅在您的网站上(因此拥有令牌是一项额外的安全措施 措施)。但是对于您而言,删除 CSRF 令牌是完全可以的 检查生产。

【讨论】:

以上是关于403 由石墨烯-django 提供。不要使用 csrf_exempt的主要内容,如果未能解决你的问题,请参考以下文章

Django 石墨烯中继限制对用户拥有的对象的查询

Django 会话不是使用 JWT 和石墨烯生成的

石墨烯和 Django 关于关系

用石墨烯 django 数点赞

如何解决具有多对多关系的石墨烯 django 节点字段

具有外键关系的对象的石墨烯中的 GraphQL 突变