美文网首页
权限管理pundit

权限管理pundit

作者: ibob2012 | 来源:发表于2019-08-24 12:33 被阅读0次

1. 原理

对应关系.png

Permission定义两个字段:action和resource。分别与Rails的Controller和Model对应。

Model关系定义

classUser<ActiveRecord::Basehas_and_belongs_to_many:roleshas_many:permissions,through::rolesend

classRole<ActiveRecord::Basehas_many:permissions,dependent::destroyhas_and_belongs_to_many:usersend

classPermission<ActiveRecord::Basebelongs_to:rolehas_many:users,through::roleend

定义权限

classApplicationPolicyclass<<selfdefactions@actions||=[]enddefpermit(action_or_actions)acts=Array(action_or_actions).collect(&:to_s)acts.eachdo|act|define_method("#{act}?"){can?act}endactions.concat(acts)endendprivatedefcan?(action)permission={action:action,resource:record.is_a?(Class)?record.name:record.class.name}user.permission.exists?(permission)endend

在ApplicationPolicy里定义一个permit方法(类方法)用来定义和保存权限点,can?方法用来做权限检查。然后就可以像这样声明权限点:

classResourcePolicy<ApplicationPolicypermit[:read,:create,:update,:destroy]end

这些Action就会被保存到ResourcePolicy.actions里。

另外还需要两个方法policies和resource:

classApplicationPolicyclass<<selfdefpolicies@policies||=Dir.chdir(Rails.root.join('app/policies'))doDir['**/*_policy.rb'].collectdo|file|file.chomp('.rb').camelize.constantizeunlessfile==File.basename(__FILE__)end.compactendenddefresourcename.chomp('Policy')endendend

分别用来获取所有的 Policy 和 每个 Policy 对应的 resource (这两个方法是通过简单的命名规则实现的, 灵活性会差一点).

2. 使用pundit

classApplicationController<ActionController::BaseincludePunditend

添加验证

$ rails g pundit:install

生成默认的policy文件,路径为app/policies/application_policy.rb

将policies目录放到rails的自动加载路径中:config/application.rb

moduleBuildAnApiRailsDemoclassApplication<Rails::Application+config.autoload_paths<<Rails.root.join('app/policies')endend

$ rails g pundit:policyuser

生成 app/policies/user_policy.rb为User模型进行权限验证。

classUserPolicy<ApplicationPolicyclassScope<Struct.new(:user,:scope)defresolvescope.allendendend

如果users_controller有这么一段

defupdate@user=Article.find(params[:id])#这里验证current_user对这个@user是否有权限@user.update_attributes(user_attributes)end

我们给UserPolicy中添加一个方法,来验证这个用户是否有这个权限。

classUserPolicy<ApplicationPolicy+defupdate?+returntrueifuser.admin?+returntrueifrecord.id==user.id+end+defshow?+returntrue+end+defcreate?+returntrue+end+defdestroy?+returntrueifuser.admin?+returntrueifrecord.id==user.id+endend

其中user和record来自于ApplicationPolicy。

然后在UsersController中添加验证

defupdate@user=User.find(params[:id])authorize@article,:update?@user.update_attributes(user_attributes)end

由于action_name和验证方法的名字相同,可以简写

defupdate@user=User.find(params[:id])authorize@article@user.update_attributes(user_attributes)end

这是,我们已经进行了权限验证,当用户不具备权限的时候回抛出错误,不能不处理,需要捕获错误进行处理。

classApplicationController<ActionController::BaseincludePunditrescue_fromPundit::NotAuthorizedError,with::user_not_authorizedprivatedefuser_not_authorizedredirect_to root_url,:alert=>"You don't have permission to those resources."endend

3人点赞

Rails4笔记

相关文章

网友评论

      本文标题:权限管理pundit

      本文链接:https://www.haomeiwen.com/subject/qjofectx.html