GraphQL/ Rails 422 Unprocessable Entity - сохранение токена в сессию
В настоящее время я работаю над изменением рельсового бэкенда проекта с REST на graphql, и я сталкиваюсь с ошибкой аутентификации после их учебника - https://www.howtographql.com/graphql-ruby/4-authentication/
Я использую движок GraphiQL для проверки всех своих запросов и получения ошибки status 422 unprocessable Entity, User Must Exist
Это имеет смысл, потому что мутация, которую я выполняю, заключается в создании нового цвета, который имеет belongs_to
отношение к пользователю.
Примерно на полпути по ссылке выше ^^^ написано так:
С маркером, что
signinUser
обеспечивает мутацию, приложения могут аутентифицировать последующие запросы. Есть несколько способов сделать это. В этом уроке мы просто собираемся использовать встроенный сеанс, поскольку он не добавляет никаких требований к клиентскому приложению. Сервер 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
2 ответа
Мой коллега отметил, что "сессия" является частью рельсов и должна создать 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
и это добавило куки обратно в приложение / позволило мне сделать следующий запрос с существующим пользователем.
Вы также можете добавить эти строки, которые я нашел в "Lysender" в его посте - Rails 5 - Только API - Включить Cookies и Сессии, если вы не хотите удалять функцию только для API.
config.api_only = true
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore, key: '_coookie_name', expire_after: 30.days
Аналогично API REST 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