执行POST时,CSRF令牌会在标头中传递

时间:2017-07-02 14:31:54

标签: django vue.js apollo

我在Django之上设置了VueJS SPA。我在/api上运行了Graphene端点,graphiql中的查询运行正常。我已经设置了前端,我正在使用Apollo Client来查询服务器。有我的设置:

const CSRFtoken = Cookies.get('csrftoken')

const networkInterface = createNetworkInterface({
  uri: '/api',
  transportBatching: true
})

networkInterface.use([{
  applyMiddleware (req, next) {
    if (!req.options.headers) {
      req.options.headers = {}  // Create the header object if needed.
    }
    req.options.headers['X-CSRFToken'] = CSRFtoken
    console.log('applied middleware')
    next()
  }
}])

const apolloClient = new ApolloClient({
  networkInterface,
  connectToDevTools: true
})

Vue.use(VueApollo)

const apolloProvider = new VueApollo({
  defaultClient: apolloClient
})

new Vue({
  el: '#app',
  apolloProvider,
  render: h => h(App)
});

我的POST请求包含{X-CSRFToken'标头,其值由Cookies提供。截图如下: Request Headers

不幸的是,Django禁止访问(错误403),并显示消息:“CSRF cookie missing”。

我在网上搜索过但找不到相关内容。

提前致谢!

1 个答案:

答案 0 :(得分:3)

TL; DR:问题是标题中没有Cookie,包括csrftoken

要解决此问题,请附加

  opts: {
    credentials: 'same-origin'
  }

createNetworkInterface初始化,如下所示。

// headers for auth
const networkInterface = createNetworkInterface({
  uri: '//localhost:8000/api',
  transportBatching: true,
  opts: {
    credentials: 'same-origin'
  }
})

长篇故事:

过去两天我一直在摆弄这个问题,询问Django和Apollo社区频道。我非常绝望,所以我考虑从Apollo转换到其他GraphQL客户端。我查看了http://graphql.org/graphql-js/graphql-clients/处的参考实现。它看起来像这样:

var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.open("POST", "/graphql");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");
xhr.onload = function () {
  console.log('data returned:', xhr.response);
}
xhr.send(JSON.stringify({query: "{ hello }"}));

我把它扔进我的代码中,将CSRF令牌cookie添加到标题中并检查 - 它有效。我真的很开心,但想知道为什么一个工作,而另一个则不工作。如上所述,我发现Apollo的请求缺少Cookies Header。实际上XMLHttpRequest con是你不能在不添加Cookie的情况下发送请求 - 而Fetch API允许你这样做。 Apollo基于Fetch API。我检查了客户端的文档,它就在那里。 :)