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

Posted

技术标签:

【中文标题】执行 POST 时,CSRF 令牌在标头中传递【英文标题】:CSRF token gets passed in the header when performing POST 【发布时间】:2017-12-05 21:57:01 【问题描述】:

我正在 Django 之上设置 VueJS SPA。我在/api 上运行石墨烯端点,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 提供。截图如下:

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

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

提前致谢!

【问题讨论】:

那么...您的问题是什么,您收到 CSRF 错误了吗? 是的,403 Forbidden,Django 说它缺少 CSRF cookie。 如果您记录const CSRFtoken,该值是否正确? 是的,看起来不错 【参考方案1】:

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。我检查了客户的文档,它就在那里。 :)

【讨论】:

以上是关于执行 POST 时,CSRF 令牌在标头中传递的主要内容,如果未能解决你的问题,请参考以下文章

当 POST 是唯一方法时,如何使用 jQuery 从标头中检索 csrf 令牌?

jQuery AJAX POST 在第一次调用时跳过 Django CSRF 令牌标头

Spring MVC 4 AngularJS 1.3 HTTP POST 具有空 CSRF 令牌或标头

如何将 Django 的 CSRF 令牌添加到 jQuery POST 请求的标头?

将 csrf 令牌传递给客户端应用程序

如何在 ajax POST 请求中设置标头以包含 CSRF 令牌