3

我目前正在将项目的 Rails 后端从 REST 更改为 graphql,并且在他们的教程之后我遇到了身份验证错误 - https://www.howtographql.com/graphql-ruby/4-authentication/

我正在使用 GraphiQL 引擎来测试我的所有请求和接收错误status 422 unprocessable Entity, User Must Exist

这是有道理的,因为我正在执行的突变是创建一种新颜色——它belongs_to与用户有关系。

大约在上面链接的页面的一半^^^它说:

使用signinUser突变提供的令牌,应用程序可以验证后续请求。有几种方法可以做到这一点。在本教程中,我们将只使用内置 session,因为这不会向客户端应用程序添加任何要求。GraphQL 服务器应该能够从每个请求的会话标头中获取令牌,检测与它相关的用户,并将此信息传递给解析器。

我能够通过signinUser之前在同一页面上显示的文档之类的方法成功返回身份验证令牌 - 它发布的方法也在此方法中将令牌保存到此假定会话(也来自上面发布的同一链接^ ^^) :

def call(_obj, args, ctx)
    input = args[:email]

    return unless input

    user = User.find_by email: input[:email]

    return unless user
    return unless user.authenticate(input[:password_digest])

    crypt = ActiveSupport::MessageEncryptor.new(ENV["SECRET_BASE_KEY"])

    token = crypt.encrypt_and_sign("user-id:#{ user.id }")

    puts "please **********************************"
    p ctx[:session]


    ctx[:session][:token] = token

    puts "please **********************************"
    p ctx[:session]

    OpenStruct.new({
      user: user,
      token: token
      })
  end

您将能够在我的拼命挣扎中看到,我在方法返回之前就退出了会话,并且毫不奇怪地看到它包含用户登录的令牌。

但是,当我继续执行突变以创建颜色时,我的期望是会话仍将包含该标记,并且我能够成功提交该颜色。情况并非如此,当我为这个请求退出会话时,它返回一个空哈希。

我找不到任何关于内置 graphql会话如何工作的信息——而且我对 graphql 来说是全新的。


我的主要问题是——graphql会话是否应该缓存令牌信息?为什么信息没有传递给以下请求signinUser?由于文档声称这种身份验证方法不是长期解决方案,我是否应该尝试在本教程中使用身份验证?


我知道这很多,但真的很感激在这方面有额外的大脑。

提前致谢!

PS。我了解本教程使用链接,并且我在这里使用颜色- 这是故意的,我已尽力确保语义差异不会导致任何错误。

  • Rails 版本 - 5.2.2(仅使用 api)

  • graphql - 1.7.4

  • graphiql 导轨 - 1.4.4

4

2 回答 2

0

与 REST API 相同,GraphQL 不会在两个后续请求之间存储任何信息,您必须将登录突变返回的身份验证令牌传递给您想要当前用户相关信息的所有后续请求。

你应该在下面做类似的事情graphql_controller.rb

class GraphqlController < ApplicationController
  def execute
    variables = ensure_hash(params[:variables])
    query = params[:query]
    operation_name = params[:operationName]
    context = {
      current_user: current_user
    }
    result = GraphqlTutorialSchema.execute(query, variables: variables, context: context, operation_name: operation_name)

    render json: result
  end

  private

  # set current user here
  def current_user
    # you can token here
    token = request.headers['Authorization']
    return nil unless token
    # find current user from this token
  end

  # Handle form data, JSON body, or a blank value
  def ensure_hash(ambiguous_param)
    # ...code
  end
end
于 2019-01-21T09:08:35.250 回答
0

我的一位同事指出,“会话”是 rails 的一部分,应该创建一个可以从下一个请求访问的 cookie。

我提到我使用的是 Rails 版本 - 5.2.2(仅使用 api) - 当您-api在初始化新的 rails 项目时使用标志时,它将这些行添加到application.rb

# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers
# -- all .rb files in that directory are automatically loaded after loading
# the framework and any gems in your application.

# Only loads a smaller set of middleware suitable for API only apps.
# Middleware like session, flash, cookies can be added back manually.
# Skip views, helpers and assets when generating a new resource.
config.api_only = true

特别注意这一行 -Middleware like session, flash, cookies can be added back manually.


我注释掉了config.api_only = true,这将 cookie 添加回应用程序/允许我向现有用户发出下一个请求。

如果您不想删除仅 api 功能,您还可以添加我从“Lysender”的帖子中找到的这些行 - Rails 5 – API Only – Enable Cookies and Sessions 。

config.api_only = true
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore, key: '_coookie_name', expire_after: 30.days
于 2019-01-21T18:25:08.520 回答