简体   繁体   English

使用cancan和devise在Rails中授权未登录的用户行为

[英]Authorizing non-logged-in user behavior in rails with cancan and devise

Post: hidden: boolean

I want the logged in user could see all the posts, and the non-logged-in user only have access to posts whose hidden fields are false. 我希望已登录的用户可以看到所有帖子,而未登录的用户只能访问其隐藏字段为false的帖子。 So I write like this in cancan's Ability Model: 所以我在坎康的能力模型中这样写:

if user_signed_in?
    can :read, Post
else 
    can :read, Post, :hidden => false
end

but accessing the helper user_signed_in is not allowed in Model. 但是在Model中不允许访问助手user_signed_in。 As stated in this question: Rails 3 devise, current_user is not accessible in a Model ? 如这个问题所述: Rails 3设计,在模型中不能访问current_user? . While we could using some tricks to access the helper, its not proper to do that 尽管我们可以使用一些技巧来访问帮助程序,但这样做不合适

So, how could I authorize the not-logged-in user properly? 那么,如何正确授权未登录的用户? Or just use "Include" to use this helper ?? 或者只是使用“包含”来使用此帮助程序?

Or should I put this in authentication part? 还是应该将其放入身份验证部分? but how? 但是如何?

All you need to do is this: 您需要做的就是:

def initialize(user)
  user ||= User.new # guest user (not logged in)

  can :read, Post, :hidden => false

  if User.exists?(user)
    can :read, Post
  end
end

With devise, the current_user helper method returns the current user when logged in but returns nil when not logged in. It is available in the controllers and views. 通过devise, current_user帮助程序方法在登录时返回当前用户,但在未登录时返回nil。在控制器和视图中可用。 By default, CanCan does all authorization checks against the return of the current_user method. 默认情况下,CanCan会针对current_user方法的返回执行所有授权检查。

Now whenever the can? 现在何时can? method is called from a view or a controller, the return of current_user will be passed to a new instance of Ability as the local variable user . 方法是从一个视图或控制器调用,返回current_user将被传递到的一个新实例Ability作为本地变量user

To check if the user was logged in, I choose to use User.exists?() . 要检查用户是否已登录,我选择使用User.exists?() It's a class method for ActiveRecord::Base that will check if that user object is persisted in the database. 这是ActiveRecord::Base的类方法,它将检查该user对象是否保留在数据库中。 Any other way will work just as well though. 任何其他方式都将同样有效。 For instance, this would work just as well or better: 例如,这将同样或更好地工作:

if user.encrypted_password
  can :read, Post
end

This will check if the default devise password field exists for the user instance. 这将检查user实例的默认设备密码字段是否存在。 If you haven't done anything too crazy, this will only return a value if the user is logged in. If the second option works for your situation, it may be superior because you won't even have to query the database. 如果您还没有做任何疯狂的事情,那么只有在用户登录后,它才会返回一个值。如果第二个选项适合您的情况,那么它可能会更好,因为您甚至不必查询数据库。

Semi-relevant tip, check out a role handling gem like Rolify . 半相关提示,请查看处理Rolify之类的角色 It is great when used in conjunction with CanCan. 与CanCan结合使用时效果很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM