Django / Graphene / Apollo / django-webpack-loader / Vue:CORS / CSRF不能一起工作吗?

时间:2019-05-21 15:22:25

标签: django vue.js cors csrf apollo

我正在一个项目中使用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/'

编辑:如果我用graphql/包装csrf_exempt api urlpath,它会起作用:

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

但这是BadIdea(TM)的安全性。如何使用Vue和Django和webpack_loader将令牌传递到前端?

1 个答案:

答案 0 :(得分:1)

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

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

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

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

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

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