我正在一个项目中使用Django作为后端,Vue作为前端,并尝试实现Apollo / Graphene / GraphQL作为数据传输层。 大多数功能都可以,但是我对CORS / CSRF设置一无所知。
有人知道如何通过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:8000,http://localhost:8000/admin和http://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 serve
在http://localhost:8080上运行
* ./manage.py runserver
在http://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将令牌传递到前端?
答案 0 :(得分:1)
跳过对该请求的 CSRF 检查可能没问题,但很难根据您提供的信息对其进行评估,所以让我首先解释为什么我们需要 CSRF 检查。
CSRF 旨在修复 HTTP 和 Web 浏览器工作方式中存在的“漏洞”。这个漏洞如下:任何网站都可以包含一个 from 向您的网站提交数据,当这样做时,cookies 将沿着用户提交的表单传递。
这意味着第 3 方网站可以诱使您的用户在您的网站上执行某些操作。为了防止这种情况,创建了 CSRF 令牌的想法。简单地说:您网站上的任何表单负责执行任何可能对用户造成任何伤害的行为,当被 3rd 方网站欺骗提交时,必须在为此操作提交的所有数据旁边包含一个 CSRF 令牌字段.相同的 CSRF 令牌需要出现在用户的会话或 cookie 中。提交表单时,将比较这两个令牌,如果它们不匹配或其中任何一个不存在,则表单将被拒绝。
这可以保护由第 3 方网站提交的任何表格,因为来自您网站的 cookie 无法被其他网站读取,即使它们与来自此类网站的请求一起传递。那么该网站就不可能在表单数据中设置匹配的令牌。
话虽如此,当您不使用 cookie 保持用户会话时,不会出现此问题。当您的前端位于不同的域时,这也不是问题,因为来自前端的所有请求都将带有 Origin
标头及其域名。因此,如果是其中任何一种情况,您可以相应地禁用 CSRF 检查:
CSRF_TRUSTED_ORIGINS
将其列入白名单。