CanCan中最安全,最Rails的方式来做Guest,User,Admin权限

时间:2011-03-01 17:50:55

标签: ruby-on-rails ruby-on-rails-3 cancan

我对rails(3)比较陌生,正在构建一个使用CanCan的应用程序,其中有3层用户。

  • 访客 - 未注册的访客用户
  • 已注册并登录访客
  • 管理员 - 已注册并已登录 带有管理员标志的访客

我的能力现在是bog-stock,从cancan docs复制,基本上定义了guest角色和admin角色

class Ability

    include CanCan::Ability

    def initialize(user)
        user ||= User.new # Guest user

        if user.is_admin?
            can :manage, :all
        else
            can :read, [Asana,Image,User,Video,Sequence]
        end
    end

end

我想添加用户角色。由于我正在创建那个一次性用户模型,我想过使用new_record?确定用户是否已登录。类似的东西:

class Ability

    include CanCan::Ability

    def initialize(user)
        user ||= User.new # Guest user

        if !user.new_record? and user.is_admin?
            can :manage, :all
        elsif !user.new_record? and !user.is_admin?
            can {registered user-y permissions}
        else
            can :read, [Asana,Image,User,Video,Sequence]
        end
    end

end

但是,感觉不对。似乎与实际登录相似,并且担心其实际上是否安全。

以更优雅的方式寻求建议。

谢谢!

5 个答案:

答案 0 :(得分:21)

好问题,我使用较低到较高权限的方法:

class Ability  
  include CanCan::Ability  

  def initialize(user)
    # Guest User 
    unless user 
      can :read, [Asana,Image,User,Video,Sequence]
    else
      # All registered users
      can {registered user-y permissions}
      # Admins 
      if user.is_admin?
        can :manage, :all
      end
    end 
  end  
end

这样一来,如果明天你还有其他角色可以集成,你可以这样添加一个case语句:

class Ability  
  include CanCan::Ability  

  def initialize(user)
    # Guest User 
    unless user 
      can :read, [Asana,Image,User,Video,Sequence]
    else
      # All registered users
      can {registered user-y permissions}
      # Different roles
      case user.role
      when 'admin'
        can :manage, :all
      when 'manager'
        can :manage, [Video, Image, Sequence]
      end
    end 
  end  
end

答案 1 :(得分:2)

那么你基本上想要的是没有登录用户的能力,登录用户的能力以及登录管理员的能力?

因为当前用户模型被传递到初始化,所以你将不得不根据用户的属性进行测试,并且使用存储在用户模型上的基本角色属性是有意义的,例如

def initialize(user)
user ||= User.new # guest user (not logged in)
if user.role == 'admin'
  # Admin roles
  can :manage, :all
elsif user.role == 'user'
  # Signed in user permissions
else
  # Guest permissions
  can :read, :all
end

因此,当用户注册/注册时,您可以将角色值默认为“user”,然后允许某些方法在管理界面中将其更新为“admin”。你可以使用一个管理员吗?检查用户,因为这对于访客和普通登录用户来说都是错误的。

答案 2 :(得分:1)

如果用户对象不是new_record,则表示它存储在数据库中。对我来说,足以接受它是一个登录用户。

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new  

    # Guest users
    can :create, User

    # Members  
    unless user.new_record?
      can [:edit, :update], User, :id => user.id
    end

    # Admins
    if user.admin?
      can :manage, :all
    end
  end
end

此外,有时管理功能不一定非常花哨 - 也许这就是你需要的全部内容?

class User < ActiveRecord::Base
  # Alternatively, you can add an admin attribute flag
  def admin?
    ["theadmin@yourservice.com", "hisspouse.yourservice.com"].include?(email)
  end
end

最后,虽然您不熟悉rails,但我建议您从头开始编写自己的身份验证。使用像Devise和Authlogic这样的宝石似乎总是有它的缺点。它并不一定非常复杂。 Ryan(康康的作者)对这个主题进行了精彩的截屏:http://railscasts.com/episodes/250-authentication-from-scratch

答案 3 :(得分:0)

如果您确实拥有持久用户模型,那么这是一个登录用户,否则他们是访客。也许你过分思考这个?

class Ability
  include CanCan::Ability

  def initialize(user=nil)
    if user && user.is_admin?
      can :manage, :all
    elsif user
      can {registered user-y permissions}
    else # guest
      can :read, [Asana,Image,User,Video,Sequence]
    end
  end
end

答案 4 :(得分:0)

如果使用角色继承,则此模式运行良好:

能力

user ||= User::GUEST # guest user (not logged in)

# anyone
can [:read], Post

# any registered user
if user.role? :user
  can [:comment], Post
end

# editor
if user.role? :editor
  can [:create], Post
end

# admin
if user.role? :admin
  can [:manage], Post
end

用户

GUEST = User.new.tap {|u| u.role = 'guest'}

ROLES = %w[guest user editor admin]
def role?(base_role)
  begin
    ROLES.index(base_role.to_s) <= ROLES.index(role.to_s)
  rescue
    raise "invalid role query '#{base_role}' against user role '#{role}'"
  end
end