澳门新葡萄京娱乐场 6

澳门新葡萄京娱乐场关于RBAC的学习资料

“权限”是我们设计系统必不可少的,关于“权限”的英语单词也很多,该用哪个呢?我参照有关“权限”的英文软件,总结如下,不足之处,多多指正:

Authorization

说说权限的一些东东,不是Authentication,是Authorization。
澳门新葡萄京娱乐场 1

 

简单说就是access control即访问控制,控制用户对某个资源的访问。
比如说,是否可以查看某个页面、修改某个数据,甚至能不能看到某个按钮。

我们通常用三种元素进行授权操作,分别是:

  • Permissions:
    这个在Shiro中代表粒度(granularity)最小的(原子性)的安全策略。
    权限的粒度也可以再细化三个等级:

    • 资源:比如我可以对用户信息进行修改
    • 实例:我可以对用户A的信息进行修改
    • 属性:我可以对用户A的信息中的姓名进行修改

    通常情况下,资源都支持CRUD操作。但是,每一种操作对一个资源有着不同的意义。
    所以我们尽力将权限的粒度做的小一些。
    Permission仅仅声明对某个资源可以进行什么样的操作。
    比如:能否看到“删除用户”按钮?能否浏览用户列表页面?

  • Roles:
    Role可以说是一系列动作的集合,通常将Role分配给User,User有没有操作权限归因于Role。
    Role有两种类型,分别是隐式(implicity)和显示(explicity)。

    • Implicity Roles:根据某个角色判断是否对资源有操作权限,粒度较粗。
    • Explicity
      Roles:关注是否有进行该操作的权限,角色只是聚合了权限,用户拥有某角色。
      也可以理解为基于角色的访问权限控制与基于资源的访问权限控制(总之我讨厌这种咬文嚼字的感觉,但我们又有必要有效地表达出我们的想法)。
      一般更建议使用基于资源的访问权限控制。
  • Users: 即操作的主体,和Subject是一样的概念。
    可以根据角色或者权限决定是否允许用户执行某个操作。
    当然,我们可以直接将权限分配给用户,也可以将权限分配给角色再将角色分配给用户。
    或者我们也可以根据具体的需求再加一个层级。

权限判断主要有3方式,分别是:

  • 编码方式:
    先说说基于角色的控制,相对基于资源的控制来得简单些。
    关键是最后两行代码:

    Subject currentUser = SecurityUtils.getSubject();
    UsernamePasswordToken token = new UsernamePasswordToken("King","t;stmdtkg");
    currentUser.login(token);
    
    currentUser.hasRole("admin");
    currentUser.checkRole("admin");
    //用角色判断主要是两类方法,hasRole*和checkRole*,前者返回boolean,后者抛出异常。
    boolean hasRole(String roleIdentifier);
    boolean[] hasRoles(List<String> roleIdentifiers);
    boolean hasAllRoles(Collection<String> roleIdentifiers);
    
    void checkRole(String roleIdentifier) throws AuthorizationException;
    void checkRoles(Collection<String> roleIdentifiers) throws AuthorizationException;
    void checkRoles(String... roleIdentifiers) throws AuthorizationException;
    

 

通常,基于资源的控制较基于角色的控制更加有效。
用资源判断也是两类方法,isPermitted和checkPermission,前者返回boolean,后者抛出异常。
但与基于角色的方法不同的是,基于资源的方法的参数除了String也可以是org.apache.shiro.authz.Permission类型。
Permission是一接口,自定义一个Permission只需要实现boolean
implies(Permission p)。
如果想更准确地表达一个权限,或者想在权限执行时增加一些逻辑或访问一些资源则可以用Permission对象。

  • 注解方式:
    在方法上面加上权限注解。
    澳门新葡萄京娱乐场 2

    @RequiresRoles({"admin","leader"})
    public void deleteUsers(){
        //...
    }
    

    解释一下这五个annotation:

    • @RequiresAuthentication:访问或者调用被注解的类或者方法时通过认证。
    • @RequiresGuest:需要从未通过认证且没有被记住(Remember me)。
    • @RequiresPremissions:需要特定的权限。
    • @RequiresRoles:需要特定的角色。
    • @RequiresUser:需要已通过认证
  • 页面标签: 我们可以根据权限去影响页面的显示

    <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
    
    <shiro:hasPermission name="user!delete.do">
        <a href="###">删除用户</a>
    </shiro:hasPermission>
    

 

今天在学习RBAC的时候在网上查了一些资料,本来想保存一个地址的,但是怕将来地址打不开,所以就复制过来吧,如有侵权之处,你来信告之,我会在第一时间删除!

Permission:权限,包括动作和客体,比如:添加文档,“添加”是动作,“文档”是客体。相近的也有:Access
Control。

Authorization Sequence

澳门新葡萄京娱乐场 3
图转自Shiro官网,但是这个步骤是在是太罗嗦了。

RBAC初学笔记

什么是RBAC?

RBAC就是Role-Based Access
Control,基于角色的访问控制。角色访问控制(RBAC)引入了Role的概念,目的是为了隔离User(即动作主体,Subject)与Privilege(权限,表示对Resource的一个操作,即Operation+Resource)
,更符合企业的用户、组织、数据和应用特征。

RBAC的关注点在于Role与user,Role与privilege的关系,也就是User
Assignment与Permission Assignment的关系。

RBAC有以下优点:

1、 减少授权管理的复杂性,降低管理开销
  2、 灵活的支持企业的安全策略,对企业的变化有很大的伸缩性

 

解决复杂的权限管理问题的过程可以抽象概括为:判断【Who是否可以对What进行How的访问操作(Operator)】这个逻辑表达式的值是否为True的求解过程。

RBAC中的几个重要概念:

l        
Who:权限的拥有者或主体。典型的有Principal、User、Group、Role、Actor等等。跟授权有关系的实体就只有角色(Role)和用户(User)。譬如:业务经理(Role),张三(User)

Role:作为一个用户(User)与权限(Privilege)的代理层,解耦了权限和用户的关系,所有的授权应该给予Role而不是直接给User或Group。基于角色的访问控制方法的思想就是把对用户的授权分成两部份,用角色来充当用户行驶权限的中介。角色是一组访问权限的集合,一个用户可以是很多角色的成员,一个角色也可以有很多个权限,而一个权限也可以重复配置于多个角色。

User:用户就是一个可以独立访问计算机系统中的数据或者用数据表示的其它资源的主体,我们用USERS表示一个用户集合。用户在一般情况下是指人。

Group:是一组相关user的集合。User从group继承出来,也就具有了该group的角色权限。

个人觉得可以这么认为,role是抽象化了的user或group。

l         What:权限针对的资源(Resource)(包括资源类别(the type
of Resource)和资源实例(the instance of Resource))。譬如:报表。

粗粒度:表示类别级,即仅考虑对象的类别(the type of
object),不考虑对象的某个特定实例。比如,用户管理中,创建、删除,对所有的用户都一视同仁,并不区分操作的具体对象实例。

细粒度:表示实例级,即需要考虑具体对象的实例(the instance of
object),当然,细粒度是在考虑粗粒度的对象类别之后才再考虑特定实例。比如,合同管理中,列表、删除,需要区分该合同实例是否为当前用户所创建。

l        
How:亦作action,表示某种访问方法(亦请参考Operator条目解释)。譬如:删除。

Operator:操作。表示施加于What的How动作。是一种Resource
Related的概念,单独的How动作是没有实际意义的,譬如:删除;只有与具体资源结合在一起才有意义,譬如:删除报表。

下面的图展示了user,group,role,how的关系

 

 澳门新葡萄京娱乐场 4

权限系统的核心由以下三部分构成:

1.      创造权限

2.       分配权限

3.       使用权限

 

系统各部分的主要参与者对照如下:

1.创造权限 – Programer创造,

2.分配权限 – Administrator 分配,

3.使用权限 – User

 

 

  1. Programer 向权限系统提供 Operator = Privilege + Resource
  2. Administrator 利用 Operator
    这个基本元素,来创造他理想中的权限模型。
    如,创建角色,创建用户组,给用户组分配用户,将用户组与角色关联等等…
    这些操作都是由 Administrator 来完成的.
  3. User 使用 Administrator 分配给的权限去使用各个系统。

程序员只要回答一个问题,就是, 什么权限可以访问什么资源,也就是前面说的
Operator。程序员提供 Operator 就意味着给系统穿上了盔甲。Administrator
就可以按照他的意愿来建立他所希望的权限框架。Operator是这个系统中最关键的部分,它是一个纽带,一个系在Programmer,Administrator,User之间的纽带。(转自:)

RBAC
模型初探

访问控制背景

    访问控制技术是由美国国防部(Department of Defense,
DoD)资助的研究和开发成果演变而来的。这一研究导致两种基本类型访问控制的产生:自主访问控制(Discretionary
Access Control, DAC)和强制访问控制(Mandatory Access Control,
MAC)。最初的研究和应用主要是为了防止机密信息被未经授权者访问,近期的应用主要是把这些策略应用到为商业领域。

   
自主访问控制,允许把访问控制权的授予和取消留给个体用户来判断。为没有访问控制权的个体用户授予和废除许可。自主访问控制机制允许用户被授权和
取消访问其控制之下的任何客体(object),换句话说,用户就是他们控制下的客体的拥有者。然而,对于多数组织来说,最终用户对所访问的信息没有拥有权。对于这些组织,公司或代理机构是事实上的系统客体和处理他们的程序的拥有者。访问优先权受组织控制,而且也常常基于雇员功能而不是数据所有权。

   强制访问控制,在美国国防部 Trusted Computer Security Evaluation
Criteria (TCSEC)
中定义如下:“一种限制访问客体的手段,它以包含在这些客体中的信息敏感性和访问这些敏感性信息的主体的正式授权信息(如清除)为基础”。
  
  
以上访问控制策略对于处理一些无需保密但又敏感的信息的政府和行业组织的需求并不是特别的适合。在这样的环境下,安全目标支持产生于现有法律、道德规范、规章、或一般惯例的高端组织策略。这些环境通常需要控制个体行为的能力,而不仅仅是如何根据信息的敏感性为其设置标签从而访问这一信息的个人能力。
    

什么是基于角色访问控制(Role-Based Access Control, RBAC)?NIST
有如下定义。
  
  
访问是一种利用计算机资源去做某件事情的的能力,访问控制是一种手段,通过它这种能力在某些情况下被允许或者受限制(通常是通过物理上和基于系统的控制)。基于计算机的访问控制不仅可规定是“谁”或某个操作有权使用特定系统资源,而且也能规定被允许的访问类型。这些控制方式可在计算机系统或者外部设备中实现。
  
   
就基于角色访问控制而言,访问决策是基于角色的,个体用户是某个组织的一部分。用户具有指派的角色(比如医生、护士、出纳、经理)。定义角色的过程应该基于对组织运转的彻底分析,应该包括来自一个组织中更广范围用户的输入。
   
   
访问权按角色名分组,资源的使用受限于授权给假定关联角色的个体。例如,在一个医院系统中,医生角色可能包括进行诊断、开据处方、指示实验室化验等;而研究员的角色则被限制在收集用于研究的匿名临床信息工作上。
   
   
控制访问角色的运用可能是一种开发和加强企业特殊安全策略,进行安全管理过程流程化的有效手段。
     

用户(User)和角色(Role)

    用户指访问系统中的资源的主体,一般为人,也可为 Agent
等智能程序。角色指应用领域内一种权力和责任的语义综合体,可以是一个抽象概念,也可以是对应于实际系统中的特定语义体,比如组织内部的职务等。针对角色属性的不同,某些模型中将角色进一步细分为普通角色和管理员角色(可理解为全局角色)。

 

许可(Permissions)和权限(Permission)

   
许可描述了角色对计算机资源的访问和操作所具有的权限,其反映的是授权的结果。比如授予某个角色对计算机资源有读的权限,则代表了一个许可的存在,这个许可表示:角色获取了对计算机资源的读许可。针对操作来说,其描述的是许可和操作之间的一种关联关系,而这层关系则表示了某一角色对某一操作所具有的权限及权限状态。

     
角色和指派(Assignment)

   
指派包含两个方面,用户指派和许可指派。用户指派表示的是,将用户指派给特定的角色。许可指派表示的是为角色指派计算机资源的访问和操作许可。

 

会话(session)

   
会话表示的是用户和角色之间的关系。用户每次必须通过建立会话来激活角色,得到相应的访问权限。

 

角色和角色等级(Role Hierarchies)

   
角色本身仅仅只是一个名词,其本身并不能代表权限的大小。比如,我们可以定一个“Director”的角色,也可以定一个“Project
Leader”的角色。对于现实中我们来说,看到这样两个角色,就清楚 DIR
的权限要比一个 PL
的权限级别高。但是对计算机来说,这两个角色仅仅是两个“词语”,是等同的。可以采用分等级角色,在角色上实现层次化来解决这些问题。也可以采用复合角色(其表示的就是一个角色组的概念),对角色实现一定的分组和复合,以便于权限指派。在一些
OA 产品中经常出现分等级角色。
   

限制(Constraints)
   
    模型中的职责分离关系(Separation of
Duty),用于控制冲突(Conflict)。静态职责分离(Static
SD)指定角色的互斥关系,用于用户指派阶段。避免同一用户拥有互斥的角色。实现简单,角色互斥语义关系清楚,便于管理不够灵活,不能处理某些实际情况。动态职责分离(Dynamic
SD)指定角色的互斥关系,用于角色激活阶段。允许同一用户拥有某些互斥的角色,但是不允许该用户同时激活互斥的角色。更灵活,直接与会话挂钩,适应实际管理需要,实现复杂,不易管理。

              澳门新葡萄京娱乐场 5

 

 

参考文献

《AN INTRODUCTION TO ROLE-BASED ACCESS CONTROL》 NIST

《工作流授权控制模型》        胡长城

《基于角色的权限管理综述》 俞诗鹏

 最后,感谢徐俊刚博士对本文翻译提供的指导。   
(请注意!引用、转贴本文应注明原作者:Rosen Jiang
以及出处:
http://www.blogjava.net/rosen

Privilege:权力,在 Permission
的基础上加一个主体,比如:小张可以添加文档,多了个主体小张。相近的也有:Entitlement、Authority。

Step 1.

Subject实例(一般为DelegatingSubject)的权限验证方法被调用(也就是hasRole,checkRole,isPermitted,checkPermission这一系列)。
DelegatingSubject:

public boolean isPermitted(String permission) {
    return hasPrincipals() && securityManager.isPermitted(getPrincipals(), permission);
}

Authorization:授权、许可,比如:小张获得了添加文档的许可。相近的也有:Eligibility。注意与
Authentication(认证)相区别。

 

所以,我认为应该用 Permission。在 .NET
中,有一个命名空间叫
System.Security.Permissions。

Step 2.

获取所有的principals并将权限验证的工作委托给securityManager。
AuthorizingSecurityManager:

public boolean isPermitted(PrincipalCollection principals, String permissionString) {
    return this.authorizer.isPermitted(principals, permissionString);
}

 

Step 3.

securityManager直接将工作委托给其内部的authorizer。

public AuthorizingSecurityManager() {
    super();
    this.authorizer = new ModularRealmAuthorizer();
}

默认为ModularRealmAuthorizer,ModularRealmAuthorizer支持与多个Realm进行交互。
ModularRealmAuthorizer循环检查每一个Realm是否实现了Authorizer,检查通过则调用该Realm的权限验证方法。
ModularRealmAuthorizer:

public boolean isPermitted(PrincipalCollection principals, String permission) {
    assertRealmsConfigured();
    for (Realm realm : getRealms()) {
        if (!(realm instanceof Authorizer)) continue;
        if (((Authorizer) realm).isPermitted(principals, permission)) {
            return true;
        }
    }
    return false;
}

 

Step 4.

Realm的权限验证方法被调用,从权限信息中获取权限集合,循环调用其implies方法判断是否拥有权限。
澳门新葡萄京娱乐场 6
(如图,部分Realm也实现了Authorizer。

另外AuthorizingRealm的constructor中

this.permissionResolver = new WildcardPermissionResolver();  

 

如果传入的权限是以String形式表示,则需要一个resolvePermission的过程。
此处会用到PermissionResolver将字符串转为Permission实例。
如果Realm的权限验证方法出现异常,异常将作为AuthorizationException传至Subject的caller。
而随后的Realm的验证方法都不会得到执行。
如果Realm的权限验证方法返回boolean(比如hasRole或者isPermitted)并且其中一个返回true,剩余的Realm则全部短路。

public boolean isPermitted(PrincipalCollection principals, String permission) {
    Permission p = getPermissionResolver().resolvePermission(permission);
    return isPermitted(principals, p);
}

public boolean isPermitted(PrincipalCollection principals, Permission permission) {
    AuthorizationInfo info = getAuthorizationInfo(principals);
    return isPermitted(permission, info);
}

private boolean isPermitted(Permission permission, AuthorizationInfo info) {
    Collection<Permission> perms = getPermissions(info);
    if (perms != null && !perms.isEmpty()) {
        for (Permission perm : perms) {
            if (perm.implies(permission)) {
                return true;
            }
        }
    }
    return false;
}

 

PermissionResolver

顺便说说这个PermissionResolver,主要用于将以String表示的权限转为Permission实例。
如果想定义一个PermissionResolver,我们只需要实现一个方法。

public interface PermissionResolver {
    /**
     * Resolves a Permission based on the given String representation.
     *
     * @param permissionString the String representation of a permission.
     * @return A Permission object that can be used internally to determine a subject's permissions.
     * @throws InvalidPermissionStringException
     *          if the permission string is not valid for this resolver.
     */
    Permission resolvePermission(String permissionString);

}

上面说过AuthorizingRealm(注意他下面还跟着一大票Realm)中默认使用的PermissionResolver实例为WildcardPermissionResolver。
什么是WildcardPemission?

用String表述权限的时候,即使我用”看用户列表页”、”晚上跑楼梯”、”open a
file”这种字符串来描述也是没有问题的。
但是他没有可以利用的规则,我们无法用某种规则去解释他(当然,有些情况下可能不需要解释)。
Shiro提供了更直观有力的表述语法——WildcardPermission。*

*比如我对某个资源有某些操作权限。
举个栗子,对用户有查看权限

user:query

 

不仅有查看权限,还有增加、修改和删除

user:query
user:edit
user:create
user:delete

 

也可以写成

"user:query,edit,create,delete"

 

如果对某个资源有所有操作权限,则:

user:*

 

或者也可以对所有资源拥有查看权限:

*:query

 

如果要表示仅对某资源的某实例有某权限,则

user:query:king

 

当然,”*”也适用于实例级别的权限

user:*:king

 

继续说说PermissionResolver。
当以String表述权限时,多数AuthorizingRealm的实现都会先将其转换为Permission实例后再进行权限检查逻辑。
权限检查并不是单纯的字符串比较。基于Permission对象的权限检查可以呈现更好的逻辑,比如wildcardPermission中如果包含”*”什么的就不是字符串比较那么简单了。
因此,几乎所有的Realm都需要将String转为Permission对象。
在Realm进行权限验证工作的上一层,也就是Authorizer中如果传递一个String表述的权限过来,Realm则使用PermissionResolver将其转换为Permission并开始验证工作。
所有做权限验证的Realm都默认使用WildcardPermissionResovler实例。
可能我们有更厉害的权限String语法,而且想让所有的Realm都支持这个语法。
这个时候我们可以自己定义一个PermissionResolver并将其设置为全局PermissionResolver(global
PermissionResolver)。
比如在.ini配置文件中:

globalPermissionResolver = com.foo.bar.authz.MyPermissionResolver
securityManager.authorizer.permissionResolver = $globalPermissionResolver

 

如果想配置一个全局PermissionResolver,每一个被注入的Realm都需要实现PermissionResolverAware接口。
当然,如果是集成AuthorizingRealm就不用想这些了,因为…

public abstract class AuthorizingRealm extends AuthenticatingRealm
        implements Authorizer, Initializable, PermissionResolverAware, RolePermissionResolverAware

 

当然,也可以使用下面的方法显示地指定一个PermissionResolver。

public void setPermissionResolver(PermissionResolver permissionResolver) {
    this.permissionResolver = permissionResolver;
    applyPermissionResolverToRealms();
}

 

或者在.ini中…

permissionResolver = com.foo.bar.authz.MyPermissionResolver

realm = com.foo.bar.realm.MyCustomRealm
realm.permissionResolver = $permissionResolver

 

相应地,RolePermissionResolver也是同理,只不过PermissionResolver是解析为Permission对象,而RolePermissionResolver是将角色String解析为Permission对象集合。

发表评论

电子邮件地址不会被公开。 必填项已用*标注