执行 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 令牌或标头