庚茗溪澈 發表於 2023-8-23 00:00:00

RBAC简介_动力节点Java学院整理

<p>
        <strong>什么是权限管理</strong></p>
<p>
        基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源。</p>
<p>
        权限管理包括用户身份认证和授权两部分,简称认证授权。对于需要访问控制的资源用户首先经过身份认证,认证通过后用户具有该资源的访问权限方可访问。</p>
<p>
        <strong>用户身份认证</strong></p>
<p>
        身份认证,就是判断一个用户是否为合法用户的处理过程。最常用的简单身份认证方式是系统通过核对用户输入的用户名和口令,看其是否与系统中存储的该用户的用户名和口令一致,来判断用户身份是否正确。对于采用指纹等系统,则出示指纹;对于硬件key等刷卡系统,则需要刷卡。</p>
<p>
        <b> </b>用户名密码身份认证流程</p>
<p>
         <img title="RBAC简介_动力节点Java学院整理" alt="RBAC简介_动力节点Java学院整理" height="489" src="https://zhuji.jb51.net/uploads/img/202305/23dad6f05640a9ea12fa4f4106d3c510.jpg" width="521"></p>
<p>
         关键对象</p>
<p>
        上边的流程图中需要理解以下关键对象:</p>
<p>
        <b>subject</b><b>:主体</b></p>
<p>
        访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体;</p>
<p>
        n <b>principal</b><b>:身份信息</b></p>
<p>
        是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等,一个主体可以有多个身份,但是必须有一个主身份(primary principal)。</p>
<p>
        n <b>credential</b><b>:凭证信息</b></p>
<p>
        是只有主体自己知道的安全信息,如密码、证书等。</p>
<p>
        <strong>授权</strong></p>
<p>
        授权,即访问控制,控制谁能访问哪些资源。主体进行身份认证后需要分配权限方可访问系统的资源,对于某些资源没有权限是无法访问的。</p>
<p>
        <strong>授权流程</strong></p>
<p>
         下图中橙色为授权流程。</p>
<p>
        <img title="RBAC简介_动力节点Java学院整理" alt="RBAC简介_动力节点Java学院整理" height="428" src="https://zhuji.jb51.net/uploads/img/202305/c74c52f712c21a01f179110f4184eacc.jpg" width="554"></p>
<p>
        <strong>关键对象</strong></p>
<p>
        授权可简单理解为who对what(which)进行how操作:</p>
<p>
        n who,即主体(subject),主体需要访问系统中的资源。</p>
<p>
        n what,即资源(resource),如系统菜单、页面、按钮、类方法、系统商品信息等。资源包括资源类型和资源实例,比如商品信息为资源类型,类型为t01的商品为资源实例,编号为001的商品信息也属于资源实例。</p>
<p>
        n how,权限/许可(permission),规定了主体对资源的操作许可,权限离开资源没有意义,如用户查询权限、用户添加权限、某个类方法的调用权限、编号为001用户的修改权限等,通过权限可知主体对哪些资源都有哪些操作许可。</p>
<p>
        权限分为粗颗粒和细颗粒,粗颗粒权限是指对资源类型的权限,细颗粒权限是对资源实例的权限。</p>
<p>
        <strong>主体、资源、权限关系如下图:</strong></p>
<p>
         <img title="RBAC简介_动力节点Java学院整理" alt="RBAC简介_动力节点Java学院整理" height="311" src="https://zhuji.jb51.net/uploads/img/202305/f53f63ef9f11214310f6b0be49545814.jpg" width="457"></p>
<p>
        <strong>权限模型</strong></p>
<p>
        对上节中的主体、资源、权限通过数据模型表示。</p>
<p>
        主体(账号、密码)</p>
<p>
        资源(资源名称、访问地址)</p>
<p>
        权限(权限名称、资源id)</p>
<p>
        角色(角色名称)</p>
<p>
        角色和权限关系(角色id、权限id)</p>
<p>
        主体和角色关系(主体id、角色id)</p>
<p>
        如下图:</p>
<p>
        <img title="RBAC简介_动力节点Java学院整理" alt="RBAC简介_动力节点Java学院整理" height="211" src="https://zhuji.jb51.net/uploads/img/202305/f93ee486dd7010d254dad3e4bc1f3574.jpg" width="554"></p>
<p>
        通常企业开发中将资源和权限表合并为一张权限表,如下:</p>
<p>
        资源(资源名称、访问地址)</p>
<p>
        权限(权限名称、资源id)</p>
<p>
        合并为:</p>
<p>
        权限(权限名称、资源名称、资源访问地址)</p>
<p>
         <img title="RBAC简介_动力节点Java学院整理" alt="RBAC简介_动力节点Java学院整理" height="280" src="https://zhuji.jb51.net/uploads/img/202305/dce7e0fbce02af9f3d713df927abf025.jpg" width="352"></p>
<p>
        上图常被称为权限管理的通用模型,不过企业在开发中根据系统自身的特点还会对上图进行修改,但是用户、角色、权限、用户角色关系、角色权限关系是需要去理解的。</p>
<p>
        <strong>权限分配</strong></p>
<p>
        对主体分配权限,主体只允许在权限范围内对资源进行操作,比如:对u01用户分配商品修改权限,u01用户只能对商品进行修改。</p>
<p>
        权限分配的数据通常需要持久化,根据上边的数据模型创建表并将用户的权限信息存储在数据库中。</p>
<p>
        <b> </b>权限控制</p>
<p>
        用户拥有了权限即可操作权限范围内的资源,系统不知道主体是否具有访问权限需要对用户的访问进行控制。</p>
<p>
        <strong>基于角色的访问控制</strong></p>
<p>
        <span>rbac基于角色的访问控制(role-based access control)是以角色为中心进行访问控制,比如:主体的角色为总经理可以查询企业运营报表,查询员工工资信息等,访问控制流程如下:</span></p>
<p>
         <img title="RBAC简介_动力节点Java学院整理" alt="RBAC简介_动力节点Java学院整理" height="280" src="https://zhuji.jb51.net/uploads/img/202305/f8f50aa6cf9c35cf38bfd2a417fc78da.jpg" width="352"></p>
<p>
        上图中的判断逻辑代码可以理解为:</p>
<div class="jb51code">
        <div>
                <div class="syntaxhighlightersql" id="highlighter_86841">
                        <div class="toolbar">
                                <span>?</span>
</div>
                        <table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
                                                        <div class="line number1 index0 alt2">
                                                                1</div>
                                                        <div class="line number2 index1 alt1">
                                                                2</div>
                                                        <div class="line number3 index2 alt2">
                                                                3</div>
                                                        <div class="line number4 index3 alt1">
                                                                4</div>
                                                        <div class="line number5 index4 alt2">
                                                                5</div>
                                                </td>
                                                <td class="code">
                                                        <div class="container">
                                                                <div class="line number1 index0 alt2">
                                                                        <code class="sql plain">if(主体.hasrole(</code><code class="sql string">"总经理角色id"</code><code class="sql plain">)){</code>
</div>
                                                                <div class="line number2 index1 alt1">
                                                                         </div>
                                                                <div class="line number3 index2 alt2">
                                                                        <code class="sql plain">查询工资</code>
</div>
                                                                <div class="line number4 index3 alt1">
                                                                         </div>
                                                                <div class="line number5 index4 alt2">
                                                                        <code class="sql plain">}</code>
</div>
                                                        </div>
                                                </td>
                                        </tr></tbody></table>
</div>
        </div>
</div>
<p>
        缺点:以角色进行访问控制粒度较粗,如果上图中查询工资所需要的角色变化为总经理和部门经理,此时就需要修改判断逻辑为“判断主体的角色是否是总经理或部门经理”,系统可扩展性差。</p>
<p>
        修改代码如下:</p>
<div class="jb51code">
        <div>
                <div class="syntaxhighlightersql" id="highlighter_1996">
                        <div class="toolbar">
                                <span>?</span>
</div>
                        <table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
                                                        <div class="line number1 index0 alt2">
                                                                1</div>
                                                        <div class="line number2 index1 alt1">
                                                                2</div>
                                                        <div class="line number3 index2 alt2">
                                                                3</div>
                                                        <div class="line number4 index3 alt1">
                                                                4</div>
                                                        <div class="line number5 index4 alt2">
                                                                5</div>
                                                </td>
                                                <td class="code">
                                                        <div class="container">
                                                                <div class="line number1 index0 alt2">
                                                                        <code class="sql plain">if(主体.hasrole(</code><code class="sql string">"总经理角色id"</code><code class="sql plain">) || 主体.hasrole(</code><code class="sql string">"部门经理角色id"</code><code class="sql plain">)){</code>
</div>
                                                                <div class="line number2 index1 alt1">
                                                                         </div>
                                                                <div class="line number3 index2 alt2">
                                                                        <code class="sql plain">查询工资</code>
</div>
                                                                <div class="line number4 index3 alt1">
                                                                         </div>
                                                                <div class="line number5 index4 alt2">
                                                                        <code class="sql plain">}</code>
</div>
                                                        </div>
                                                </td>
                                        </tr></tbody></table>
</div>
        </div>
</div>
<p>
        <strong>基于资源的访问控制</strong></p>
<p>
        rbac基于资源的访问控制(resource-based access control)是以资源为中心进行访问控制,比如:主体必须具有查询工资权限才可以查询员工工资信息等,访问控制流程如下:</p>
<p>
        上图中的判断逻辑代码可以理解为:</p>
<div class="jb51code">
        <div>
                <div class="syntaxhighlightersql" id="highlighter_120167">
                        <div class="toolbar">
                                <span>?</span>
</div>
                        <table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
                                                        <div class="line number1 index0 alt2">
                                                                1</div>
                                                        <div class="line number2 index1 alt1">
                                                                2</div>
                                                        <div class="line number3 index2 alt2">
                                                                3</div>
                                                        <div class="line number4 index3 alt1">
                                                                4</div>
                                                        <div class="line number5 index4 alt2">
                                                                5</div>
                                                </td>
                                                <td class="code">
                                                        <div class="container">
                                                                <div class="line number1 index0 alt2">
                                                                        <code class="sql plain">if(主体.haspermission(</code><code class="sql string">"查询工资权限标识"</code><code class="sql plain">)){</code>
</div>
                                                                <div class="line number2 index1 alt1">
                                                                         </div>
                                                                <div class="line number3 index2 alt2">
                                                                        <code class="sql plain">查询工资</code>
</div>
                                                                <div class="line number4 index3 alt1">
                                                                         </div>
                                                                <div class="line number5 index4 alt2">
                                                                        <code class="sql plain">}</code>
</div>
                                                        </div>
                                                </td>
                                        </tr></tbody></table>
</div>
        </div>
</div>
<p>
        优点:系统设计时定义好查询工资的权限标识,即使查询工资所需要的角色变化为总经理和部门经理也只需要将“查询工资信息权限”添加到“部门经理角色”的权限列表中,判断逻辑不用修改,系统可扩展性强。</p>
<p>
        <strong>权限管理解决方案</strong></p>
<p>
        <strong>粗颗粒度和细颗粒度</strong></p>
<p>
        <strong> 什么是粗颗粒度和细颗粒度</strong></p>
<p>
        对资源类型的管理称为粗颗粒度权限管理,即只控制到菜单、按钮、方法,粗粒度的例子比如:用户具有用户管理的权限,具有导出订单明细的权限。对资源实例的控制称为细颗粒度权限管理,即控制到数据级别的权限,比如:用户只允许修改本部门的员工信息,用户只允许导出自己创建的订单明细。</p>
<p>
         如何实现粗颗粒度和细颗粒度</p>
<p>
        对于粗颗粒度的权限管理可以很容易做系统架构级别的功能,即系统功能操作使用统一的粗颗粒度的权限管理。</p>
<p>
        对于细颗粒度的权限管理不建议做成系统架构级别的功能,因为对数据级别的控制是系统的业务需求,随着业务需求的变更业务功能变化的可能性很大,建议对数据级别的权限控制在业务层个性化开发,比如:用户只允许修改自己创建的商品信息可以在service接口添加校验实现,service接口需要传入当前操作人的标识,与商品信息创建人标识对比,不一致则不允许修改商品信息。</p>
頁: [1]
查看完整版本: RBAC简介_动力节点Java学院整理