Я работаю над проектом, который разделен на два приложения: - один рельс JSON API, который имеет дело с базой данных и передает данные как JSON - один «фронт» -end "rails, которое отправляет запросы API каждый раз, когда это необходимо, и отображать json-данные в приятном ключе.Несанкционированный запрос с использованием методов проверки подлинности как API для сброса пароля
Аутентификация для API - это токен, основанный на использовании gem'simple_token_authentication'
, что означает, что для большинства запросов, отправляемых в API, вы должны отправить токен пользователя & свой адрес электронной почты в заголовке, чтобы запрос был авторизирован.
Тот, кто работал над проектом передо мной, также установил систему аутентификации Devise на стороне API, чтобы разрешить прямой доступ к API-методам из навигатора после успешного входа с помощью пароля электронной почты &.
Я только начал кодирование в «интерфейсном приложении», которое должно запрашивать API, и у меня возникают проблемы, особенно с системой аутентификации.
Поскольку Devise уже установлен на API, я подумал, что было бы неплохо сделать логин пользователя в интерфейсном приложении, которое затем запросит методы разработки, представленные в API, для создания пароля пользователя, auth, реселлера ...
Проблема заключается в том, что методы devise представляют собой рендеринг html, а не JSON, поэтому я фактически должен был переопределить большинство контроллеров разработчика. Чтобы дать вам краткое представление о том, как это работает: Вы заполняете форму для регистрации в интерфейсном приложении, после чего параметры отправляются в интерфейсный контроллер приложений, который затем запрашивает у пользователя метод регистрации пользователя в API:
1) передний конец контроллер приложения:
def create
# Post on API to create USER
@response = HTTParty.post(ENV['API_ADDRESS']+'users',
:body => { :password => params[:user][:password],
:password_confirmation => params[:user][:password_confirmation],
:email => params[:user][:email]
}.to_json,
:headers => { 'Content-Type' => 'application/json' })
# si le User est bien crée je récupère son email et son token, je les store en session et je redirige vers Account#new
if user_id = @response["id"]
session[:user_email] = @response["email"]
session[:user_token] = @response["authentication_token"]
redirect_to new_account_path
else
puts @response
@errors = @response["errors"]
puts @errors
render :new
end
end
2) API-перекрытая разработать контроллер:
class RegistrationsController < Devise::RegistrationsController
def new
super
end
def create
@user = User.new(user_params)
if @user.save
render :json => @user
else
render_error
end
end
def update
super
end
private
def user_params
params.require(:registration).permit(:password, :email)
end
def render_error
render json: { errors: @user.errors.full_messages }, status: :unprocessable_entity
end
end
Это работает нормально. Здесь я отправляю обратно пользователя, который был только что создан на API, как JSON, и я храню это токен аутентификации и его адрес электронной почты в сеансе hash.
Моя проблема связана с методом reset_password, для которого я пытаюсь повторно использовать некоторые из кода разработки. Во-первых, я прошу сбросить пароль, который генерирует токен для сброса пароля для пользователя, который запросил изменение. Это также генерирует электронное письмо пользователю со ссылкой (с токеном внутри), указывающим на форму пароля сброса для конкретного пользователя. Это хорошо работает.Я получаю ссылку в электронном письме, затем собирается в виде edit_password на моем фронтального приложение:
Изменить пароль
<form action="https://stackoverflow.com/users/password" method='post'>
<input name="authenticity_token" value="<%= form_authenticity_token %>" type="hidden">
<%= hidden_field_tag "[user][reset_password_token]", params[:reset_password_token] %>
<%=label_tag "Password" %>
<input type="text" name="[user][password">
<%=label_tag "Password Confirmation" %>
<input type="text" name="[user][password_confirmation]">
<input type="Submit" value="change my password">
</form>
Когда форма отправлена она проходит через мой передний конец контроллера приложения:
def update_password
@response = HTTParty.patch(ENV['API_ADDRESS']+'users/password',
:body => {
:user => {
:password => params[:user][:password],
:password_confirmation => params[:user][:password_confirmation],
:reset_password_token => params[:user][:reset_password_token]
}
}.to_json,
:headers => { 'Content-Type' => 'application/json' })
end
, который затем вызывает мой перекрытая Завещание :: PasswordController (метод обновления):
# app/controllers/registrations_controller.rb
class PasswordsController < Devise::RegistrationsController
# POST /resource/password
def create
if resource_params[:email].blank?
render_error_empty_field and return
end
self.resource = resource_class.send_reset_password_instructions(resource_params)
yield resource if block_given?
if successfully_sent?(resource)
render_success
else
render_error
end
end
def update
self.resource = resource_class.reset_password_by_token(resource_params)
yield resource if block_given?
if resource.errors.empty?
resource.unlock_access! if unlockable?(resource)
render_success
else
render_error
end
end
private
# TODO change just one big method render_error with different cases
def render_success
render json: { success: "You will receive an email with instructions on how to reset your password in a few minutes." }
end
def render_error
render json: { error: "Ce compte n'existe pas." }
end
def render_error_empty_field
render json: { error: "Merci d'entrer un email" }
end
end
Однако запрос всегда Несанкционированный:
Started PATCH "https://stackoverflow.com/users/password" for ::1 at 2016-02-05 11:28:30 +0100
Processing by PasswordsController#update as HTML
Parameters: {"user"=>{"password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "reset_password_token"=>"[FILTERED]"}, "password"=>{"user"=>{"password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "reset_password_token"=>"[FILTERED]"}}}
Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms)
Я не понимаю, почему этот последний запрос несанкционированный?
спасибо @max. Я думаю, что я уже использую аутентификацию на основе токенов с помощью gem '' 'simple_token_authentication''': при создании пользователя он автоматически генерирует auth_token, и когда этот пользователь входит в систему, API отображает токен аутентификации в интерфейсном приложении ; Я храню его в '' 'session []' '', и затем, в каждом запросе, который пользователь делает впоследствии, пока он не выйдет из системы, я отправляю auth_token в заголовках.Как вы говорите, вероятно, мало пользы в разработке, если мне нужно переопределить каждого отдельного редактора, но скажете ли вы, что система токенов, которую я описал здесь, является хорошим решением в моем случае? –
Я не уверен - вы используете сеанс в своем приложении API? Если это так - нет, это не очень хорошая идея, поскольку файлы cookie оставляют API открытым для XSRF. – max
no Я не думаю, что я использую сеансы в своем API, API должен быть доступен только из внешнего приложения с использованием токена, аналогичного тому, что я описал в своем предыдущем комментарии. Не будет способа получить доступ к API за счет прямого входа в API для ex, вам всегда придется пройти через это приложение переднего плана и получить свой токен от API. Это яснее? –