美文网首页
权限管理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