仅在root_path上登录后才重定向用户

时间:2011-12-27 01:11:03

标签: ruby-on-rails ruby ruby-on-rails-3.1 devise

我的Rails应用程序上有一个root_path,它不受用户保护,即它是一个简单的门户网站主页,带有登录表单。

用户登录后,我希望转到dashboard_path

我做到了这一点:

def signed_in_root_path(scope_or_resource)
  dashboard_path
end

这显然应该在用户登录时使用,我不希望它转到root_path,同时如果用户试图攻击限制区域仍然保持用户返回上一页它已超时或未登录。

即:

restricted_pa​​ge - >登录 - > restricted_pa​​ge_but_logged_in

我不想改变这种行为,这就是为什么我没有使用after_sign_in_path,但希望重定向它,如果它在root_path上,或任何不需要用户身份验证的路由。

我的问题是这不起作用。登录后,我将重定向回root_path,我认为这是因为after_sign_in_path之前被触发了。

有没有办法做到这一点?谢谢!

编辑:这是我第二次登录时工作,即我转到root_path,登录,获取闪存消息,说明我已登录,并在表单上再次输入用户名和密码root_path。我成功地被重定向到dashboard_path。不过,不是我想要的行为。

8 个答案:

答案 0 :(得分:22)

只是一个想法

您可以为登录的网址定义两个根网址,这将指向信息中心,第二个用于非登录用户,这将指向登录页面

根据一些约束定义不同的根URL 在routes.rb中

已登录用户的根网址

constraints(AuthenticatedUser) do 
  root :to => "dashboard"
end

非签名用户的根网址

root :to=>"users/signin"

然后在lib / authenticated_user.rb中创建类AuthenticatedUser

class AuthenticatedUser
  def self.matches?(request)
    user_signed_in?
  end
end

现在,如果用户登录root_url将指向仪表板,否则它将指向登录页面

你也可以创建两个根(尚未测试)

root :to => "dashboard", :constraints => {user_signed_in?}
root :to => "users/signin"

更多关于约束 http://edgeguides.rubyonrails.org/routing.html#request-based-constraints

注意

url的优先级基于创建顺序,  首次创建 - >最高优先级资源

答案 1 :(得分:4)

听起来你的问题太复杂了。如果你进入覆盖路由变量,它只会导致头痛。如果您使用的是单独的控制器,我建议您使用之前的过滤器来要求登录并使用except param或在过滤之前跳过该目标。举个例子:

class ApplicationController < ActionController::Base

  before_filter :require_login, :except => :root

  def root
    # Homepage
  end

  protected

  def require_login
    redirect_to login_path and return unless logged_in?
  end

end

(确保您已定义了logged_in?)

如果您使用的是单独的控制器,它将如下所示:

class HomepageController < ApplicationController

  skip_before_filter :require_login
  before_filter :route

  protected

  def route
    redirect_to dashboard_path and return if logged_in?
  end

end

关于登录后的正确路由,这可以归结为您在创建会话时所执行的操作。无论如何,此设置应该捕获任何登录尝试访问主页的人,并将它们路由到您的仪表板以及任何尝试访问受限内容的人(除root之外的任何内容)并将其路由到login_path

答案 2 :(得分:2)

您可以覆盖after_sign_in_path_for方法,而不会丢失所需的行为。

 def after_sign_in_path_for(resource_or_scope)
   stored_location_for(resource_or_scope) || dashboard_path
 end

如果current_user存在,我还会在root_path操作中添加一个重定向的条件。

RootController.rb

def index
  if current_user
     redirect_to dashboard_path
  else
    super #or whatever
  end
end

如果您想将重定向添加到许多不受保护的操作中,您还可以使用before_filter。

答案 3 :(得分:1)

我正在使用Omniauth,这种方法对我来说效果很好。如果你正在使用不同的策略,我相信你可以修改它。

登录后,只需将它们重定向到root_path即可将它们带到dashboard_path或您在下面路线文件中设置的其他默认值。

在app控制器中设置助手和回调方法:

# application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery
  helper_method :current_user

  private

  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end

  def authenticate_user!
    unless current_user
      redirect_to root_url
    end
  end
end

before_filter放入受限制的控制器中以捕获未经授权的人员:

# dashboard_controller.rb
class DashboardController < ActionController::Base
  before_filter :authenticate_user!

  def index
  end

  # rest of controller here

end

将这两项添加到路线中。如果不满足条件,则不会执行第一个。如果是,则顶部优先,所有root_url调用将转到仪表板

# routes.rb
YourAppName::Application.routes.draw do
  root :to => 'dashboard#index', :conditions => lambda{ |req| !req.session["user_id"].blank? }
  root :to => 'static_page#index'

  # the rest of your routes

end

答案 4 :(得分:0)

我认为你的解决方案比必要的更复杂。为什么不在登录表单发布到的操作上执行这样简单的操作:

def login
  // logic to check whether login credentials authorize user to sign in
  // say 'user_signed_in?' is boolean to determine whether user has successfully signed in
  redirect_to(user_signed_in? ? dashboard_path : root_path)
end

答案 5 :(得分:0)

登录表单是在每个页面(顶部/侧边栏)上还是您有登录页面?

如果每个页面都有,您可以使用request.referrer来了解用户来自哪里。

答案 6 :(得分:0)

您可以使用应用程序控制器上的before_filter来控制它。

答案 7 :(得分:0)

我不确定您是否在某处使用after_filter或before_filter进行重定向,但您可以在登录控制器中使用skip_filter。然后将自定义重定向作为该控制器中的过滤器。

Skip before_filter in Rails