Разработка перенаправления после сбоя входа в систему

#ruby-on-rails #redirect #login #devise

#ruby-on-rails #перенаправление #аутентификация #разработать

Вопрос:

Все найденные мной вопросы связаны с успешным входом в систему с помощью помощника after_sign_in_path_for(resource)

У меня есть форма входа в индекс сайта, и при сбое входа она перенаправляет на «users / sign_in»

Но как я могу перенаправить на свой site#index , когда не удается войти в систему?

Ответ №1:

  1. Создайте custom_failure.rb в вашем каталоге lib с:

      class CustomFailure < Devise::FailureApp
       def redirect_url
         your_path
       end
    
       def respond
         if http_auth?
           http_auth
         else
           redirect
         end
       end
     end
      
  2. В вашем инициализаторе разработки включите:

        config.warden do |manager|
         manager.failure_app = CustomFailure
       end
      
  3. Убедитесь, что Rails загружает ваши lib-файлы в ваше application.rb :

      config.autoload_paths  = %W(#{config.root}/lib)
      

Не забудьте перезапустить свой сервер.

Я не думаю, что есть более простой способ сделать это.

Комментарии:

1. Это не сработало. Я знаю, что это стандартный ответ из devise wiki.

2. Содержимое respond метода может быть переработано в http_auth? ? http_auth : redirect . Отлично работает!

3. У меня это не работает, оно по-прежнему перенаправляет обратно на логин

4. У меня это сработало с использованием Devise 3.2.4. При включении или изменении любого из этих файлов обязательно перезапускайте сервер. Вероятно, вы получите сообщение об ошибке, подобное этому: NameError - undefined local variable or method 'login' for #<CustomFailure:0x007ffc4aeb9328> если вы этого не сделаете.

5. Отлично работает в Rails 5 с Devise 4.3.0. Просто поместите файл custom_failure.rb в /app /models /concerns и пропустите шаг autoload_paths #3. Спасибо @Marcao, ты сэкономил мое время!

Ответ №2:

Если вы используете свое собственное SessionsController значение :recall , вы можете повторно присвоить auth_options значение controller#method , чтобы вызвать warden.authenticate!(auth_options) нужное перед запуском, например:

в app / controllers /users/sessions_controller.rb

 class Users::SessionsController < Devise::SessionsController
  #...
  def create
    #...
    auth_options = { :recall => 'site#index', :scope => :user }
    resource = warden.authenticate!(auth_options)
    #...
  end
  #...
end
  

Таким образом, вам не нужно создавать настраиваемое FailureApp и изменять конфигурации.

Комментарии:

1. Это изменяет URL-адрес на users / sign_in

Ответ №3:

Это то, что происходит с devise 3.1.0

 Started POST "/users/sign_in"
Processing by Devise::SessionsController#create
Completed 401 Unauthorized
Processing by Devise::SessionsController#new
  

new вызывается из-за auth_options, определенных в конце gems/devise-3.1.0/app/controllers/devise/sessions_controller.rb

Вам следует переопределить параметры auth_options, используемые в действии create. Я скопировал контроллер в app / controllers / devise /sessions_controller.rb моего приложения Rails и заменил метод auth_options следующим образом

 def auth_options
  { :scope => resource_name, :recall => "Home#new" }
end
  

Это делает свое дело, но URL по-прежнему остается /users/sign_in

Я постараюсь исправить и это.

Комментарии:

1. Сейчас я разрабатываю 3.2.2. Решение Marcao работает отлично. Нет необходимости копировать и исправлять контроллеры разработки или устанавливать auth_options.

Ответ №4:

Вы можете изменить путь входа по умолчанию.

Проверьте https://github.com/plataformatec/devise/wiki/How-To:-Change-the-default-sign_in-and-sign_out-routes

Комментарии:

1. Спасибо @MikeH, я попробовал это. devise_for : пользователи действительно получают ‘users’, :to => ‘site#index’, :as => :user_root # Rails 3 end Работает идеально, перенаправляя на мой индекс во всех случаях, за исключением сбоя входа в систему. В этом случае он перенаправляет на user / sign_in, и я хочу, чтобы меня перенаправили на «site # index».

2. Хм. При сбое входа в систему приложение devise с ошибкой перенаправляет на new_#{scope}_session_path (в вашем случае new_user_session_path). Когда вы выполняете rake routes , какой контроллер / действие отображается для этого пути к ресурсам?

3. Вы нашли ответ? Я все еще ищу это…

Ответ №5:

Развивая ответ Маркао, я настоятельно рекомендую поместить некоторый отладчик в ваш метод CustomFailure response, чтобы лучше понять, что происходит.

 Class CustomFailure < Devise::FailureApp
  def respond
    binding.pry
    super
  end
end
  

Если вы посмотрите на исходный код FailureApp Devise для метода response, очень легко понять, что происходит.

 def respond
  if http_auth?
    http_auth
  elsif warden_options[:recall]
    recall
  else
    redirect
  end
end
  

Так, например, чтобы вернуть redirect_url, вы хотели бы убедиться, что ваши respond условные обозначения кода в конечном итоге вернутся redirect .

Однако, если вы хотите, возможно, вернуть стандартный статус 401, как определено в методе http_auth, вы хотите убедиться, что ваш respond код метода возвращает http_auth .

Таким образом, вам стоит изучить определение http_auth? В частности, обратите внимание на: request.xhr? метод, который возвращает 0 для запросов json (напомним, что 0 на самом деле равно true в ruby)

 def http_auth?
  if request.xhr?
    Devise.http_authenticatable_on_xhr
  else
    !(request_format amp;amp; is_navigational_format?)
  end
end
  

И, возможно, проверьте ваши инициализаторы / файл разработки на наличие config.http_authenticatable_on_xhr or config.navigational_formats , чтобы контролировать нужный вам ответ. Эта конфигурация действительно может повлиять на то, что возвращает Devise, и часто может приводить к неожиданному поведению из-за того, что он делает здесь, под капотом.