Rails 请教一个 before_filter 针对用户是否登录的 写法

lin_style · 2012年10月17日 · 最后由 zzhattzzh 回复于 2012年10月17日 · 5177 次阅读

页面有些函数,有些是用户是否登录都可以用,有些是必须登录。比如:

before_filter :find_user, :only => [:a,:b,:c,:d]

def find_user @user = User.find_by_id(session[:user_id]) if !@user redirect_to(:controller=>"welcome",:action => "index") end end

其中:a,:b 可以不登录就能使用,如果在 find_user 里直接判断 session,如果不存在就认为是合法的,会影响到:c,:d 的使用。。这样情况下该怎么做?before_filter 支持多个 :find_user 这种做法吗?

为啥不用两个 filter?

#1 楼 @iBachue 没听明白。我觉得最简单是在 find_user 里面能判断来源的 ACTION 是什么,如果是不需要登录的 ACTION,就直接过。

匿名 #3 2012年10月17日

偶一般需要登陆的会放到下一级的域 比如/admin 那么,/admin/orders,我就会在 admin 这级的 controller 都继承 admin_controller,然后 before_filter 验证必须登陆。 而,某些 admin 下不需要登陆,就:except 咯。 如果你设计的层次设计得好,这些实现会很轻松。。。

一个方法只做一件事,且仅仅只做一件事,使一个方法成为最小的一个单元。 http://yunshuisuiyuan.iteye.com/blog/1561179

如果你需要检测权限,find_user 这个方法名不是一个很好的选择,从 find_user 意思来说,它的职责只是用来查找一个用户,给之后的 action 用. 用两个过滤器,过滤器是按写的顺序执行的。你可以先写一个过滤器查找用户,再写一个过滤器检查权限。

权限检查可以参考 typo 博客,个人觉得很不错https://github.com/fdv/typo/blob/master/vendor/plugins/typo_login_system/lib/login_system.rb current_user 方法拿到当前登录用户 logged_in?检测是否登录 login_required 提供给过滤器使用,没有登录的用户跳转到登录页面

#3 楼 @help5305fff 问题是有些是登陆和不登陆都可以的,放哪儿?写两份吗?

匿名 #6 2012年10月17日

登陆和不登陆都可以的。。。那就是不登陆。我前面说的是你可以根据你的需求和情况去做设计

#4 楼 @cxh116 你好,你说的这些我知道。这些是设计上的规范,但是现在问题是:一些页面登陆或者不登陆都可以看到,这些 ACTION 权限怎么在 before_filter 区分开来?

#6 楼 @help5305fff 不登陆是说,他可以浏览这个页面内容;如果他登陆了,这个页面就要显示他的用户信息,还可以发帖什么的。所以有个 before_filter 里的 find_user。

#6 楼 @lin_style

before_filter :find_user, :only => [:a,:b,:c,:d]
before_filter :check_permission, :only => [:c,:d]

不知道这样写符合你的业务逻辑不

匿名 #10 2012年10月17日

登陆不登陆都可以看,如果登陆了,信息里就多了一些用户自己的;如果没登陆,就通用的信息。

你是这个意思吗???

#5 楼 @lin_style 用两个filter会比较好:

before_filter find_user,  :only => [:a, :b, :c, :d]
before_filter authenticate_user,  :only => [:c, :d]

private

def find_user
  @user = User.find_by_id(session[:user_id])
end

def authenticate_user 
  @user and redirect_to(:controller=>"welcome",:action => "index")
end

另外建议楼主下次提问时吧代码格式化一下,方便大家看。

匿名 #12 2012年10月17日

@cxh116 嘎嘎,我不是楼主,我是路人甲

#12 楼 @help5305fff 哈哈 at 错人了 没头像,不仔细看就搞错了

匿名 #14 2012年10月17日

终于懂楼主要干啥了。

以我以往的做法,套用@zzhattzzh 的代码

before_filter find_user before_filter authenticate_user , :only => [:c, :d]

因为,偶页面的 head 一般都有放用户信息的,如果登陆就会展示出来,所以不做 only,嘿嘿。

#14 楼 @help5305fff #13 楼 @cxh116 #11 楼 @zzhattzzh 先谢谢大家。 如果两个 before_filter,是不是相当 before_filter 权限被弱化了?

比如以前这些 ACTION 只有登陆才能用,直接在 before_filter 里寻找 USER,如果没有就回首页,这样 before_filter 起到一个权限判断作用;

现在这些 ACTION 登陆和不登陆都可以做,那具体的权限只能到具体的 ACTION 函数里面判断。比如在 ACTION 里取到@user 信息做一些判断什么的。现在则要在 ACTION 里面判断是否有这个@user ,然后做对应的事情。

匿名 #16 2012年10月17日

好吧,那你也别两个 filter,就一个好了,验证没登陆就跳到登陆界面。 然后加一个方法,current_user,在里面查当前用户。。。

既然 before_filter 已经被弱化,为什么还要写两个 before_filter? 直接

def find_user
  if !session[:user_id]
      return
  end

  @user = User.find_by_id(session[:user_id])
  if !@user
      redirect_to(:controller=>"welcome",:action => "index")
  end
end  

然后在具体的 ACTION 函数里,判断

  def common_event_content
    #公共部分
    @event_id = params[:id]
    @event_contents = CommonEventContent.where(["event_id=?", @event_id]).order('id desc').page(params[:page]).per(10)  

    if !@user
        return
    end     
    #需要登陆部分
end

#16 楼 @help5305fff 第一次做 WEB,经验不足,,还请海涵

比较惯用的做法是一个 current_user 方法,一个 require_logined 方法,current_user 是调用的时候获取,不需要作为过滤器,require_logined 是过滤器,给需要登录的 action 加上。

实际在用的代码例子 https://github.com/chloerei/code_campo/blob/master/app/controllers/application_controller.rb

#19 楼 @Rei 多谢回答。

我现在做法是需要登陆的 都在 before_filter 加上,保证登陆 ACTION 里的@user变量是 OK 的。

主要修改在两个地方 (觉得这样改动最小了。。) 1)不需要登陆和登陆的函数里,代码整理成两部分,在做登陆逻辑前插个判断是否登陆,如果没有就直接返回了。 2)对应的 erb 文件里做一些调整显示

再次谢谢大家

#15 楼 @lin_style 看不懂你说的是什么意思。“现在这些 ACTION 登陆和不登陆都可以做,那具体的权限只能到具体的 ACTION 函数里面判断。比如在 ACTION 里取到@user 信息做一些判断什么的。现在则要在 ACTION 里面判断是否有这个@user ,然后做对应的事情。”里面“这些 action”指的是那些 action?为甚么用两个 filter 的话:"那具体的权限只能到具体的 ACTION 函数里面判断"?

需要 登录 后方可回复, 如果你还没有账号请 注册新账号