使用Rails,Graphql,Apollo客户端的无效令牌

我试图让一个基本的Rails,Graphql,Apollo-Client设置工作,但在rails侧遇到422个错误’无效的auth令牌’。

我使用apollo看起来不对吗?

它是一个带有graphql gem和apollo客户端的Rails 5应用程序。

const csrfToken = document.getElementsByName('csrf-token')[0].content const client = new ApolloClient({ networkInterface: createNetworkInterface({ uri: '/graphql', credentials: 'same-origin', headers: { 'X-CSRF-Token': csrfToken } }), }); client.query({ query: gql` query Camillo2 { user { id email created_at } } `, }) .then(data => console.log(data)) .catch(error => console.error(error)); 

Rails日志:

 Started POST "/graphql" for ::1 at 2017-03-10 08:51:58 -0800 Processing by GraphqlController#create as */* Parameters: {"query"=>"query Camillo2 {\n user {\n id\n email\n created_at\n __typename\n }\n}\n", "operationName"=>"Camillo2", "graphql"=>{"query"=>"query Camillo2 {\n user {\n id\n email\n created_at\n __typename\n }\n}\n", "operationName"=>"Camillo2"}} Can't verify CSRF token authenticity. Completed 422 Unprocessable Entity in 2ms (ActiveRecord: 0.0ms) 

自从阿波罗2.0和根据

https://github.com/apollographql/apollo-client/blob/master/Upgrade.md

就这样做吧

 const csrfToken = document.querySelector('meta[name=csrf-token]').getAttribute('content'); const client = new ApolloClient({ link: new HttpLink({ credentials: 'same-origin', headers: { 'X-CSRF-Token': csrfToken } }), cache: new InMemoryCache() }); 

我前几天在Rails上试验过Apollo,这里的配置对我有用:

 var RailsNetworkInterface = apollo.createNetworkInterface('/graphql', { credentials: 'same-origin', headers: { 'X-CSRF-Token': $("meta[name=csrf-token]").attr("content"), } }); var client = new apollo.ApolloClient({networkInterface: RailsNetworkInterface}) client.query({ query: gql`{ event(id: 7) { name } }`}) 

但是,看起来你的工作也一样好!

你能否确认正确的令牌被发送到服务器? 例如,如果您打开Chrome devtools的网络标签,然后进行查询,您是否可以在“请求标头”部分中看到X-CSRF-Token

此外,Rails可能正在更新DOM中的CSRF令牌,但NetworkInterface保留旧的陈旧CSRF令牌。 您能否确认“请求标头”部分中的令牌与标签中的当前值匹配? (我很惊讶我自己没有遇到过这个问题,使用Turbolinks Classic。)

为了澄清上面的一些答案,因为其中一个用户注意到将uri作为createNetworkInterface的第一个参数传递但在控制台中记录了一个弃用消息:你必须传入诸如“凭证”和“标题”之类的选项。作为选项对象的属性,如下所示:

 const networkInterface = createNetworkInterface({ uri: '/graphql', opts: { credentials: 'same-origin', headers: { 'X-CSRF-TOKEN': $('meta[name=csrf-token]').attr('content'), }, }, }); 

请参阅文档中的Fetch下的第二个示例: http : //dev.apollodata.com/core/network.html

这对我有用(我正在使用react_on_rails):

 import { ApolloClient, createNetworkInterface } from 'react-apollo'; import ReactOnRails from 'react-on-rails'; const networkInterface = createNetworkInterface({ uri: '/graphql', opts: { credentials: 'same-origin' } }); networkInterface.use([{ applyMiddleware(req, next) { if (!req.options.headers) { req.options.headers = { "X-CSRF-Token": ReactOnRails.authenticityToken() } } next(); } }]); const client = new ApolloClient({ networkInterface }); export default client 

我缺少opts:{credentials:’same-origin’} ,导致同样的错误:无法validationCSRF令牌的真实性。 完成422个不可处理的实体

使用apollo-boost,它有点不同。

 import ApolloClient from 'apollo-boost' const client = new ApolloClient({ fetchOptions: { credentials: 'same-origin', }, request: (operation) => { const csrfToken = document.querySelector('meta[name=csrf-token]').getAttribute('content') operation.setContext({ headers: { "X-CSRF-Token": csrfToken } }) }, }) 

这个对我来说很好。

 const csrfToken = document.querySelector('meta[name=csrf-token]').getAttribute('content'); const link = createHttpLink({ uri: '/graphql', credentials: 'same-origin', headers: { 'X-CSRF-Token': csrfToken } }); const client = new ApolloClient({ cache: new InMemoryCache(), link, }); 
Interesting Posts