graphql_devise 用于 Rails/Graphql/Apollo/React 中的身份验证。 “字段需要身份验证”错误
Posted
技术标签:
【中文标题】graphql_devise 用于 Rails/Graphql/Apollo/React 中的身份验证。 “字段需要身份验证”错误【英文标题】:graphql_devise for authentication in Rails/Graphql/Apollo/React. "field requires authentication" error 【发布时间】:2020-10-22 02:44:17 【问题描述】:我有一个项目,我正在使用 Graphql 和 React/Apollo 设置 Rails API。我已将所有 google 链接设为紫色,以寻找最佳身份验证解决方案,但似乎我无法找到明确的答案。
我决定使用 graphql_devise gem,它利用了 devise 和 devise_token_auth。我本来希望找到一个 JWT 解决方案,但就是找不到。 (如果您有任何明显的建议,请告诉我!)
首先我安装了一个单独的身份验证路由,但在设置 ApolloClient 时遇到了多个端点的问题。我不知道如何将与身份验证相关的请求定向到我的身份验证端点,而让其余的请求通过我的 graphql 请求。 (如果弄清楚这是最简单的解决方案,请告诉我!)相反,我按照文档的指示将身份验证路由安装在自己的架构中:
class MyApiSchema < GraphQL::Schema
use GraphqlDevise::SchemaPlugin.new(
query: Types::QueryType,
mutation: Types::MutationType,
resource_loaders: [
GraphqlDevise::ResourceLoader.new('User', only: [:login, :logout])
]
)
mutation(Types::MutationType)
query(Types::QueryType)
并在graphql_controller.rb中编辑了执行行:
result = MyApiSchema.execute(query, variables: variables, context: graphql_context(:user), operation_name: operation_name)
至此,在 postman 中运行测试查询就成功了。我可以在没有设置任何标头的情况下使用 userLogin 突变访问 graphql 路由,并通过客户端、uid 和令牌获得成功的响应。我的其他查询的身份验证也有效 - 使用标头成功,没有标头则拒绝。
但是当我尝试在 react 中使用 useQuery 执行相同的查询时,它不起作用。在 Chrome 的 Apollo Client Developer Tools 插件中,它也不起作用,只返回 [Object object]。通过查看“网络”选项卡中的请求,我可以看到这是相同错误的结果:"photo field requires authentication"
。
当我窥探 Rails 服务器时,我可以看到正在接收标头。我什至可以在调用执行方法之前在我的 graphql_controller 中手动验证用户,所以我认为这不是 CORS 问题。我已经在 Rails 中设置了 rack-cors gem 以公开所需的标头。
当我深入研究代码时,graphql_devise 方法set_current_resource
似乎无法返回我的用户。这似乎源于设计方法set_user_by_token
,但我一直无法弄清楚它失败的原因。
如果有人对实现此 gem 和堆栈有任何经验,我将非常感谢您的意见!如果您有更好的身份验证方法,我很想知道您的策略是什么。如果你能帮我解决这个... field requires authentication
错误,我会永远爱你。
如果我提供的信息太多/太少,或者我的问题太含糊,我们深表歉意。如果我应该知道在我的代码中询问/显示的特定内容,请告诉我。希望你能帮忙!谢谢。
【问题讨论】:
【参考方案1】:我已经设法找到了问题所在,我想我会解释一下。
将问题追溯到 devise_token_auth gem 中的set_user_by_token
方法后,我bundle open devise_token_auth
'd,并在里面放了一个byebug。这表明 @token.token
没有从标头中正确提取。
问题是我的标头 access-token
以某种方式被转换为 accessToken
,因此当设计尝试使用此密钥从请求标头中设置令牌信息时,它返回了 nil
。
我不知道这种转换发生的原因或地点。我怀疑它来自 Apollo/React 而不是 Rails,因为我的邮递员查询的标题没有改变。在反应中,当我设置标头时,它们设置为access-token
,如下所示,但似乎在我的请求生命周期的某个时刻它们被更改了。
我如何在 React 中设置标题:
const client = new ApolloClient(
cache,
link: new HttpLink(
uri: 'http://localhost:3000/graphql',
headers:
accessToken: localStorage.getItem('access-token'),
client: localStorage.getItem('client'),
uid: localStorage.getItem('uid')
,
),
);
devise_token_auth 用于从请求中选择标头的键可以在 initializers/devise_token_auth.rb 文件中更改。
我将它们编辑如下:
config.headers_names = :'access-token' => 'accessToken',
:'client' => 'client',
:'expiry' => 'expiry',
:'uid' => 'uid',
:'token-type' => 'token-type'
这意味着我的前端现在工作顺利,我可以通过身份验证执行查询/突变。但是,现在在我的邮递员查询中,如果我想让它们工作,我必须将标题更改为 accessToken
。
很高兴确切地知道我的 React 标头在什么时候更改为 camelCase,但现在,它正在工作。如果有人遇到同样的挫折,希望这会有所帮助!
【讨论】:
以上是关于graphql_devise 用于 Rails/Graphql/Apollo/React 中的身份验证。 “字段需要身份验证”错误的主要内容,如果未能解决你的问题,请参考以下文章
删除 rails 中的模型(与“rails g model Title...”相反)
Nokogiri / Rails / zlib1g-dev的问题