Ruby-on-rails 登录失败后设计重定向

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5832631/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 01:02:32  来源:igfitidea点击:

Devise redirect after login fail

ruby-on-railsredirectlogindevise

提问by Juanjo

All the questions I've found are related for a successful login with the helper after_sign_in_path_for(resource)

我发现的所有问题都与使用助手成功登录有关 after_sign_in_path_for(resource)

I have a login form in the index of the site, and when the login fails it redirects to "users/sign_in"

我在站点的索引中有一个登录表单,当登录失败时,它会重定向到“users/sign_in”

But how can I redirect to my "site#index" when the login fails?

但是,当登录失败时,如何重定向到我的“site#index”?

回答by Marco Antonio

  1. Create a custom_failure.rb in your lib directory, with:

    class CustomFailure < Devise::FailureApp
      def redirect_url
        your_path
      end
    
      def respond
        if http_auth?
          http_auth
        else
          redirect
        end
      end
    end
    
  2. In you Devise initializer, include:

      config.warden do |manager|
        manager.failure_app = CustomFailure
      end
    
  3. Make sure Rails is loadin your lib files, in your application.rb :

    config.autoload_paths += %W(#{config.root}/lib)
    
  1. 在你的 lib 目录中创建一个 custom_failure.rb,使用:

    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)
    

Don't forget to restart your server.

不要忘记重新启动服务器。

I don't think there's an easier way to do this. Good luck.

我认为没有更简单的方法可以做到这一点。祝你好运。

回答by Sibevin Wang

If you use your own SessionsController, you can re-assign the :recallvalue of auth_optionsto recall the controller#methodyou want before running warden.authenticate!(auth_options), for example:

如果您使用自己的SessionsController,则可以重新分配 的:recallauth_optionscontroller#method在运行之前调用您想要的warden.authenticate!(auth_options),例如:

in app/controllers/users/sessions_controller.rb

在 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

With this way, you don't need to create the customized FailureApp and modify the configs.

通过这种方式,您无需创建自定义的FailureApp 并修改配置。

回答by pmontrasio

This is what happens with devise 3.1.0

这就是设计 3.1.0 发生的情况

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

new gets called because of the auth_options defined at the end of gems/devise-3.1.0/app/controllers/devise/sessions_controller.rb

由于在 gems/devise-3.1.0/app/controllers/devise/sessions_controller.rb 末尾定义的 auth_options,new 被调用

You should redefine the auth_options used in the create action. I copied the controller in app/controllers/devise/sessions_controller.rb of my Rails application and replaced the auth_options method like this

您应该重新定义创建操作中使用的 auth_options。我在我的 Rails 应用程序的 app/controllers/devise/sessions_controller.rb 中复制了控制器,并像这样替换了 auth_options 方法

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

It does the trick, but the url is still /users/sign_in

它可以解决问题,但 url 仍然是 /users/sign_in

I'll try to fix that as well.

我也会尝试解决这个问题。

回答by AmitF

Elaborating on Marcao's answer, I highly recommend placing some debuggerin your CustomFailure respond method in order to better understand what is going on.

详细说明 Marcao 的答案,我强烈建议在您的 CustomFailure 响应方法中放置一些调试器,以便更好地了解发生了什么。

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

If you look at the FailureApp Devise Source Codefor the respond method it is super easy to understand what is going on.

如果您查看响应方法的FailureApp 设计源代码,则非常容易理解发生了什么。

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

So for example in order to return a redirect_url you would want to make sure that your respondcode conditionals eventually return redirect.

因此,例如为了返回一个 redirect_url,您需要确保您的respond代码条件最终返回redirect.

However if you want to maybe return a standard 401 status as defined in the http_authmethod, you want to verify that your respondmethod code returns http_auth.

但是,如果您想返回http_auth方法中定义的标准 401 状态,您需要验证您的respond方法代码是否返回http_auth.

Thus it is worth your while to look into the definition of the http_auth?In particular, note the: request.xhr?method, which will return 0 for json requests (recall that 0 actually evaluates to true in ruby)

因此,值得您花时间研究 的定义,http_auth?特别是,请注意:request.xhr?方法,它将为 json 请求返回 0(回想一下,在 ruby​​ 中 0 实际上评估为 true)

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

And maybe check your initializers/devise file for config.http_authenticatable_on_xhror config.navigational_formatsin order to control the response that you want. This configuration can really affect what Devise returns and can often lead to unexpected behavior due to what it does here under the hood.

也许检查您的初始化/色器件文件config.http_authenticatable_on_xhrconfig.navigational_formats以控制所需的响应。这种配置确实会影响 Devise 返回的内容,并且由于它在幕后所做的事情,通常会导致意外行为。