如果用户未经Devise身份验证,则重定向到登录页面。

30
我正在使用 Ruby on Rails 中的 Devise。
如果未经身份验证的用户尝试访问需要身份验证的页面,建议的重定向方式是什么?是将他们重定向到 sessions#new 页面吗?
当前,我会收到一个错误,指出没有路由与他们尝试访问的路由匹配(在生产环境中导致 404 错误)。
5个回答

73

只需将此方法添加到 application_controller.rb 中即可。

  protected
  def authenticate_user!
    if user_signed_in?
      super
    else
      redirect_to login_path, :notice => 'if you want to add a notice'
      ## if you want render 404 page
      ## render :file => File.join(Rails.root, 'public/404'), :formats => [:html], :status => 404, :layout => false
    end
  end

您可以在其他控制器上使用 before_filter 方法。

例如:

class HomesController < ApplicationController
  before_filter :authenticate_user!
  ## if you want spesific action for require authentication
  ## before_filter :authenticate_user!, :only => [:action1, :action2]
end

不要忘记将login_path添加到routes.rb

devise_scope :user do
  match '/sign-in' => "devise/sessions#new", :as => :login
end

注意:当我为我的应用程序身份验证使用设备时,我总是使用这种方式。(Rails 3.2和Rails 4.0.1)


谢谢,那个方法可行。我也意识到我的路由设置有误——我把很多路由放在了“authenticated:user”块中,这就是为什么在注销登录时尝试访问它们时会得到404错误的原因。 - Gdeglin
谢谢。这对我来说一直很好用,但也带来了其他问题。例如,当我去编辑用户注册时,会出现一个参数错误(说参数数量错误:应该是0个而不是1个),并指向def authenticate_user!行。在这里发布了问题:[链接](http://stackoverflow.com/questions/25170716/devise-ror-argument-error-when-editing-user-registration)。感谢您的帮助! - orky
2
在Rails 5中,将match '/sign-in'替换为get '/sign-in'。 - V-SHY
@sekmo,您能详细说明一下吗? - Niek
在重定向时,使用 _url 辅助函数更加安全,例如 login_urlnew_post_url 等,因为 URL 包含协议。可以在控制台上尝试运行 app.login_urlapp.login_path :-) - sekmo
显示剩余3条评论

29
你可以像GeekTol所写的那样做,或者只是放置。
before_action :authenticate_user!

在你的控制器中。

在这种情况下,Devise使用默认的authenticate_user!方法,它将重定向到“user_session_path”并使用默认的flash消息。

除非您想要自定义它,否则无需重写authenticate_user!方法。


如果使用Devise,正确答案是不需要重写,除非您想自定义。 - ben

3
我认为你可以在需要用户登录的每个控制器中添加: before_action :authenticate_user! 我是Rails初学者,但我在自己的搜索中找到了这个方法,在我的应用程序中它很有效。

2
你应该参考 Devise 的自己的如何操作:How To: Redirect to a specific page when the user can not be authenticated
我能想到的另一种选择是创建一个路由约束,包装您的受保护路由。最好按照 Devise 的方式进行操作,但这里有一个例子:
#On your routes.rb
constraints(Constraints::LoginRequired) do
  get '/example' 
end

#Somewhere like lib/constraints/login_required.rb
module Constraints
  class LoginRequired
    def self.matches?(request)
      #some devise code that checks if the user is logged in
    end 
  end
end

谢谢您的回复。关于您提供的 Devise How To,它只提供了 Rails 3 的说明,其中一些并不适用于 Rails 4。即使尝试考虑这些差异,它对我来说仍然无法正常工作。接下来将尝试您的 Constraint 建议。 - Gdeglin
感谢您提供 Devise 文档的链接。那应该是正确的方法。 - maxhm10

-6
将以下代码添加到您的config/routes.rb文件中:devise_for :usersresources :users,然后您就可以在视图中生成设备了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接