简体   繁体   English

Devise 登录失败后重定向

[英]Devise redirect after login fail

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”?

  1. Create a custom_failure.rb in your lib directory, with:在您的 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. In you Devise initializer, include:在您的 Devise 初始化程序中,包括:

     config.warden do |manager| manager.failure_app = CustomFailure end
  3. Make sure Rails is loadin your lib files, in your application.rb:确保 Rails 在你的 application.rb 中加载你的 lib 文件:

     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.祝你好运。

If you use your own SessionsController , you can re-assign the :recall value of auth_options to recall the controller#method you want before running warden.authenticate!(auth_options) , for example:如果您使用自己的SessionsController ,您可以重新分配auth_options:recall值以在运行warden.authenticate!(auth_options)之前调用您想要的controller#method #method,例如:

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 并修改配置。

This is what happens with devise 3.1.0这就是 devise 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.您应该重新定义 create 操作中使用的 auth_options。 I copied the controller in app/controllers/devise/sessions_controller.rb of my Rails application and replaced the auth_options method like this我在我的 Rails 应用程序的 app/controllers/devise/sessions_controller.rb 中复制了 controller 并像这样替换了 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.我也会尝试解决这个问题。

Elaborating on Marcao's answer, I highly recommend placing some debugger in 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 Code for the respond method it is super easy to understand what is going on.如果您查看响应方法的FailureApp Devise 源代码,很容易理解发生了什么。

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 respond code conditionals eventually return redirect .因此,例如,为了返回 redirect_url 您需要确保您的respond代码条件最终返回redirect

However if you want to maybe return a standard 401 status as defined in the http_auth method, you want to verify that your respond method 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?因此,值得您花时间研究一下http_auth? In particular, note the: request.xhr?特别要注意: request.xhr? method, which will return 0 for json requests (recall that 0 actually evaluates to true in ruby)方法,它将为 json 请求返回 0(回想一下 0 实际上在 ruby 中计算为 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_xhr or config.navigational_formats in order to control the response that you want.并且可能检查您的初始化程序/设计文件中的config.http_authenticatable_on_xhrconfig.navigational_formats以控制您想要的响应。 This configuration can really affect what Devise returns and can often lead to unexpected behavior due to what it does here under the hood.这种配置确实会影响 Devise 返回的内容,并且由于它在后台所做的事情,通常会导致意外行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM