登录失败后设计重定向

Posted

技术标签:

【中文标题】登录失败后设计重定向【英文标题】:Devise redirect after login fail 【发布时间】:2011-08-15 12:20:26 【问题描述】:

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

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

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

【问题讨论】:

【参考方案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
    

    在你的设计初始化器中,包括:

      config.warden do |manager|
        manager.failure_app = CustomFailure
      end
    

    确保 Rails 已加载到您的 lib 文件中,在您的 application.rb 中:

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

别忘了重启你的服务器。

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

【讨论】:

这不起作用。我知道这是来自设计 wiki 的常用答案。 respond方法的内容可以重构为http_auth? ? http_auth : redirect。效果很好! 这对我不起作用,它仍然重定向回登录 这对我使用 Devise 3.2.4 有效。确保在包含或更改任何这些文件时重新启动服务器。你可能会收到这样的错误:NameError - undefined local variable or method 'login' for #&lt;CustomFailure:0x007ffc4aeb9328&gt;如果你不这样做。 在带有 Devise 4.3.0 的 Rails 5 中运行良好。只需将文件 custom_failure.rb 放入 /app/models/concerns 并跳过 autoload_paths 步骤 #3。谢谢@Marcao,你节省了我的时间!【参考方案2】:

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

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

【讨论】:

这会将 url 修改为 users/sign_in【参考方案3】:

这就是设计 3.1.0 所发生的情况

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

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

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

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

它成功了,但 url 仍然是 /users/sign_in

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

【讨论】:

我现在正在设计 3.2.2。 Marcao 的解决方案非常有效。无需复制和修补设计控制器或设置 auth_options。【参考方案4】:

您可以更改默认登录路径。

查看https://github.com/plataformatec/devise/wiki/How-To:-Change-the-default-sign_in-and-sign_out-routes

【讨论】:

谢谢@MikeH,我试过了。 devise_for :users do get 'users', :to => 'site#index', :as => :user_root # Rails 3 end 在所有情况下都可以完美重定向到我的索引,登录时除外失败。在这种情况下,它重定向到 user/sign_in,我想重定向到“site#index”。 嗯。当登录失败时,设计的失败应用程序将重定向到 new_#scope_session_path (在您的情况下为 new_user_session_path)。当您执行 rake routes 时,会为此资源路径显示什么控制器/操作? 你找到答案了吗?我还在找……【参考方案5】:

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

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

如果您查看响应方法的 FailureApp Devise Source Code,则非常容易理解发生了什么。

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

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

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

因此,值得您花时间研究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

也许检查您的初始化程序/设计文件中的config.http_authenticatable_on_xhrconfig.navigational_formats 以控制您想要的响应。这种配置确实会影响 Devise 返回的内容,并且由于它在后台所做的工作,通常会导致意外行为。

【讨论】:

以上是关于登录失败后设计重定向的主要内容,如果未能解决你的问题,请参考以下文章

Grails Spring Security登录失败未重定向到登录视图

Laravel 5.0 - 登录失败时更改重定向

Abp授权失败重定向至登录页,修改为返回401

身份验证重定向失败

Android / PHP:登录成功但失败重定向到下一个活动

Spring Security:如果身份验证失败,则重定向到登录页面