精华内容
下载资源
问答
  • 此篇文章主要尝试将世面上现有的一些权限系统设计做一下简单的总结分析,个人水平有限,如有错误请不吝指出。 术语 这里对后面会用到的词汇做一个说明,老司机请直接翻到常见设计模式。 用户 发起操作的主体。 ...

    此篇文章主要尝试将世面上现有的一些权限系统设计做一下简单的总结分析,个人水平有限,如有错误请不吝指出。

    术语

    这里对后面会用到的词汇做一个说明,老司机请直接翻到常见设计模式

    用户

    发起操作的主体。

    对象(Subject)

    指操作所针对的客体对象,比如订单数据或图片文件。

    权限控制表 (ACL: Access Control List)

    用来描述权限规则或用户和权限之间关系的数据表。

    权限 (Permission)

    用来指代对某种对象的某一种操作,例如“添加文章的操作”。

    权限标识

    权限的代号,例如用“ARTICLE_ADD”来指代“添加文章的操作”权限。

    常见设计模式

    自主访问控制(DAC: Discretionary Access Control)

    系统会识别用户,然后根据被操作对象(Subject)的权限控制列表(ACL: Access Control List)或者权限控制矩阵(ACL: Access Control Matrix)的信息来决定用户的是否能对其进行哪些操作,例如读取或修改。

    而拥有对象权限的用户,又可以将该对象的权限分配给其他用户,所以称之为“自主(Discretionary)”控制。

    这种设计最常见的应用就是文件系统的权限设计,如微软的NTFS。

    DAC最大缺陷就是对权限控制比较分散,不便于管理,比如无法简单地将一组文件设置统一的权限开放给指定的一群用户。

    Windows的文件权限

    强制访问控制(MAC: Mandatory Access Control)

    MAC是为了弥补DAC权限控制过于分散的问题而诞生的。在MAC的设计中,每一个对象都都有一些权限标识,每个用户同样也会有一些权限标识,而用户能否对该对象进行操作取决于双方的权限标识的关系,这个限制判断通常是由系统硬性限制的。比如在影视作品中我们经常能看到特工在查询机密文件时,屏幕提示需要“无法访问,需要一级安全许可”,这个例子中,文件上就有“一级安全许可”的权限标识,而用户并不具有。

    MAC非常适合机密机构或者其他等级观念强烈的行业,但对于类似商业服务系统,则因为不够灵活而不能适用。

    RedHat MLS

    Red Hat: MLS

    基于角色的访问控制(RBAC: Role-Based Access Control)

    因为DAC和MAC的诸多限制,于是诞生了RBAC,并且成为了迄今为止最为普及的权限设计模型。

    RBAC在用户和权限之间引入了“角色(Role)”的概念(暂时忽略Session这个概念):

    RBAC核心设计

    图片来自Apache Directory

    如图所示,每个用户关联一个或多个角色,每个角色关联一个或多个权限,从而可以实现了非常灵活的权限管理。角色可以根据实际业务需求灵活创建,这样就省去了每新增一个用户就要关联一遍所有权限的麻烦。简单来说RBAC就是:用户关联角色,角色关联权限。另外,RBAC是可以模拟出DAC和MAC的效果的。

    例如数据库软件MongoDB便是采用RBAC模型,对数据库的操作都划分成了权限(MongoDB权限文档):

    权限标识说明
    find具有此权限的用户可以运行所有和查询有关的命令,如:aggregate、checkShardingIndex、count等。
    insert具有此权限的用户可以运行所有和新建数据有关的命令:insert和create等。
    collStats具有此权限的用户可以对指定database或collection执行collStats命令。
    viewRole具有此权限的用户可以查看指定database的角色信息。
     

    基于这些权限,MongoDB提供了一些预定义的角色(MongoDB预定义角色文档,用户也可以自己定义角色):

    角色findinsertcollStatsviewRole
    read  
    readWrite 
    dbAdmin  
    userAdmin   

    最后授予用户不同的角色,就可以实现不同粒度的权限分配了。

    目前市面上绝大部分系统在设计权限系统时都采用RBAC模型。然而也有的系统错误地实现了RBAC,他们采用的是判断用户是否具有某个角色而不是判断权限,例如以下代码:

    <?php
    
    if ($user->hasRole('hr')) {
        // 执行某种只有“HR”角色才能做的功能,例如给员工涨薪…
        // ...
    }
    

    如果后期公司规定部门经理也可以给员工涨薪,这时就不得不修改代码了。

    以上基本就是RBAC的核心设计(RBAC Core)。而基于核心概念之上,RBAC规范还提供了扩展模式。

    角色继承(Hierarchical Role)

    RBAC 1

    带有角色继承的RBAC。图片来自Apache Directory

    顾名思义,角色继承就是指角色可以继承于其他角色,在拥有其他角色权限的同时,自己还可以关联额外的权限。这种设计可以给角色分组和分层,一定程度简化了权限管理工作。

    职责分离(Separation of Duty)

    为了避免用户拥有过多权限而产生利益冲突,例如一个篮球运动员同时拥有裁判的权限(看一眼就给你判犯规狠不狠?),另一种职责分离扩展版的RBAC被提出。

    职责分离有两种模式:

    • 静态职责分离(Static Separation of Duty):用户无法同时被赋予有冲突的角色。
    • 动态职责分离(Dynamic Separation of Duty):用户在一次会话(Session)中不能同时激活自身所拥有的、互相有冲突的角色,只能选择其一。

    RBAC 2

    静态职责分离。图片来自Apache Directory

    RBAC 3

    动态职责分离。图片来自Apache Directory

    讲了这么多RBAC,都还只是在用户和权限之间进行设计,并没有涉及到用户和对象之间的权限判断,而在实际业务系统中限制用户能够使用的对象是很常见的需求。例如华中区域的销售没有权限查询华南区域的客户数据,虽然他们都具有销售的角色,而销售的角色拥有查询客户信息的权限。

    那么我们应该怎么办呢?

    用户和对象的权限控制

    在RBAC标准中并没有涉及到这个内容(RBAC基本只能做到对一类对象的控制),但是这里讲几种基于RBAC的实现方式。

    首先我们看看PHP框架Yii 1.X的解决方案(2.X中代码更为优雅,但1.X的示例代码更容易看明白):

    <?php
    
    $auth=Yii::app()->authManager;
     
    $auth->createOperation('createPost','create a post');
    $auth->createOperation('readPost','read a post');
    $auth->createOperation('updatePost','update a post');
    $auth->createOperation('deletePost','delete a post');
    
    // 主要看这里。
    // 这里创建了一个名为`updateOwnPost`的权限,并且写了一段代码用来检验用户是否为该帖子的作者
    $bizRule='return Yii::app()->user->id==$params["post"]->authID;';
    $task=$auth->createTask('updateOwnPost','update a post by author himself',$bizRule);
    $task->addChild('updatePost');
     
    $role=$auth->createRole('reader');
    $role->addChild('readPost');
     
    $role=$auth->createRole('author');
    $role->addChild('reader');
    $role->addChild('createPost');
    $role->addChild('updateOwnPost');
     
    $role=$auth->createRole('editor');
    $role->addChild('reader');
    $role->addChild('updatePost');
     
    $role=$auth->createRole('admin');
    $role->addChild('editor');
    $role->addChild('author');
    $role->addChild('deletePost');
    
    

    实现效果:

    Yii 1.X权限图

    图片来自Yii官方WiKi

    在这个Yii的官方例子中,updateOwnPost在判断用户是否具有updatePost权限的基础上更进一步判断了用户是否有权限操作这个特定的对象,并且这个判断逻辑是通过代码设置的,非常灵活。

    不过大部分时候我们并不需要这样的灵活程度,会带来额外的开发和维护成本,而另一种基于模式匹配规则的对象权限控制可能更适合。例如判断用户是否对Id为123的文章具有编辑的权限,代码可能是这样的:

    <?php
    
    // 假设articleId是动态获取的
    $articleId = 123;
    
    if ($user->can("article:edit:{$articleId}")) {
        // ...
    }
    

    而给用户授权则有多种方式可以选择:

    <?php
    
    // 允许用户编辑Id为123的文章
    $user->grant('article:edit:123');
    
    // 使用通配符,允许用户编辑所有文章
    $user->grant('article:edit:*');
    
    

    虽然不及Yii方案的灵活,但某些场景下这样就够用了。

    如果大家还有更好的方案,欢迎在评论中提出。

    基于属性的权限验证(ABAC: Attribute-Based Access Control)

    ABAC被一些人称为是权限系统设计的未来。

    不同于常见的将用户通过某种方式关联到权限的方式,ABAC则是通过动态计算一个或一组属性来是否满足某种条件来进行授权判断(可以编写简单的逻辑)。属性通常来说分为四类:用户属性(如用户年龄),环境属性(如当前时间),操作属性(如读取)和对象属性(如一篇文章,又称资源属性),所以理论上能够实现非常灵活的权限控制,几乎能满足所有类型的需求。

    例如规则:“允许所有班主任在上课时间自由进出校门”这条规则,其中,“班主任”是用户的角色属性,“上课时间”是环境属性,“进出”是操作属性,而“校门”就是对象属性了。为了实现便捷的规则设置和规则判断执行,ABAC通常有配置文件(XML、YAML等)或DSL配合规则解析引擎使用。XACML(eXtensible Access Control Markup Language)是ABAC的一个实现,但是该设计过于复杂,我还没有完全理解,故不做介绍。

    总结一下,ABAC有如下特点:

    1. 集中化管理
    2. 可以按需实现不同颗粒度的权限控制
    3. 不需要预定义判断逻辑,减轻了权限系统的维护成本,特别是在需求经常变化的系统中
    4. 定义权限时,不能直观看出用户和对象间的关系
    5. 规则如果稍微复杂一点,或者设计混乱,会给管理者维护和追查带来麻烦
    6. 权限判断需要实时执行,规则过多会导致性能问题

    既然ABAC这么好,那最流行的为什么还是RBAC呢?

    我认为主要还是因为大部分系统对权限控制并没有过多的需求,而且ABAC的管理相对来说太复杂了。Kubernetes便因为ABAC太难用,在1.8版本里引入了RBAC的方案

    ABAC有时也被称为PBAC(Policy-Based Access Control)或CBAC(Claims-Based Access Control)。

    结语

    权限系统设计可谓博大精深,这篇文章只是介绍了一点皮毛。

    随着人类在信息化道路上越走越远,权限系统的设计也在不断创新,但目前好像处在了平台期。

    可能因为在RBAC到ABAC之间有着巨大的鸿沟,无法轻易跨越,也可能是一些基于RBAC的微创新方案还不够规范化从而做到普及。不过在服务化架构的浪潮下,未来这一块必然有极高的需求,也许巨头们已经开始布局了。



    作者:该叶无法找到
    链接:https://www.jianshu.com/p/ce0944b4a903
    来源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    展开全文
  • 权限系统设计模型以及SpringSecurity框架实现权限系统设计模型介绍SpringSecurity使用Role认证实现粗粒度RBAC基本的 用户-角色 表设计参考Gradle引入SpringSecurity依赖测试用的ControllerSpringSecurity配置类...

    Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

    人们使用Spring Security有很多种原因,不过通常吸引他们的是在J2EE Servlet规范或EJB规范中找不到典型企业应用场景的解决方案。
    特别要指出的是他们不能在WAR 或 EAR 级别进行移植。
    这样,如果更换服务器环境,就要,在新的目标环境进行大量的工作,对应用系统进行重新配置安全。
    使用Spring Security 解决了这些问题,也提供很多有用的,完全可以指定的其他安全特性。
    可能知道,安全包括两个主要操作。
    第一个被称为“认证”,是为用户建立一个他所声明的主体。主体一般是指用户,设备或可以在系统中执行动作的其他系统。
    第二个叫“授权”,指的是一个用户能否在应用中执行某个操作,在到达授权判断之前,身份的主体已经由身份验证过程建立。
    这些概念是通用的,不是Spring Security特有的。
    在身份验证层面,Spring Security广泛支持各种身份验证模式,这些验证模型绝大多数都由第三方提供,或者正在开发的有关标准机构提供的,例如 Internet Engineering Task Force.
    作为补充,Spring Security 也提供了自己的一套验证功能。
    Spring Security 目前支持认证一体化如下认证技术:
    1、HTTP BASIC authentication headers (一个基于IEFT RFC 的标准)
    2、HTTP Digest authentication headers (一个基于IEFT RFC 的标准)
    3、HTTP X.509 client certificate exchange (一个基于IEFT RFC 的标准)
    4、LDAP (一个非常常见的跨平台认证需要做法,特别是在大环境)
    5、Form-based authentication (提供简单用户接口的需求)
    6、OpenID authentication
    7、Computer Associates Siteminder
    8、JA-SIG Central Authentication Service (CAS,这是一个流行的开源单点登录系统)
    9、Transparent authentication context propagation for Remote Method Invocation and HttpInvoker (一个Spring远程调用协议)

    权限系统设计模型介绍

    参考文章 权限系统设计模型分析(DAC,MAC,RBAC,ABAC)

    SpringSecurity糅合Role认证与Authority实现权限系统

    这个demo演示如何使用springsecurity的两种验证,并不对应任何权限设计模型。在基于Role和Authority两种验证授权的方式下灵活应对各种业务需求。
    此demo的Git地址

    基本的 用户-角色 表设计参考

    在这里插入图片描述
    四个个User:
    aa : ROLE_ADMIN
    bb : ROLE_NORMAL
    cc : AUTH_PUSH
    dd : AUTH_PUSH 和 AUTH_POP

    这样设计权限都是根据一个个角色分配的,用户要使用某个操作的权限就需要拥有对应的角色。

    Gradle引入SpringSecurity依赖

        implementation 'org.springframework.boot:spring-boot-starter-security'
       
        testImplementation 'org.springframework.security:spring-security-test'
    

    测试用的Controller

    ActionRole/Auth
    /anymous
    /sayhi/{id}anymous
    /sayhello/{name}ROLE_ADMIN
    /goodbye/{name}ROLE_ADMIN / ROLE_NORMAL
    /pushAUTH_PUSH / AUTH_POP
    /popAUTH_POP

    为了表达出Spring Security配置的灵活性,/sayhello action在SecurityConfig配置类中配置,/goodbyte action在方法前用注解配置(需要开启@EnableGlobalMethodSecurity (prePostEnabled = true)
    )。

    @Controller
    public class TestController {
    
        public static volatile Integer countNumber =0;
    
        @RequestMapping("/")
        public String HomeIndexPage(){
            return "/Views/Index";
        }
        @RequestMapping("/loginPage")
        public String LoginPage(){
            return "/Views/Login";
        }
    
        @RequestMapping("/loginProc")
        public String loginProcAction(){
            System.out.println("come in Login processing");
            return "/";
        }
        @ResponseBody
        @RequestMapping("/sayhi/{id}")
        public JSONObject firstAction(@Null @PathVariable("id")String id){
            if(id==null)
                id = "001";
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("Id",id);
            synchronized (countNumber) {
            jsonObject.put("number", ++countNumber);
                jsonObject.put("Action", "sayhi+id");
            }
            return jsonObject;
        }
    
        @ResponseBody
        @RequestMapping("/sayhello/{name}")
        public JSONObject secondAction(@Nullable @PathVariable("name")String id){
            if(id==null)
                id = "001";
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("Id",id);
            synchronized (countNumber) {
                jsonObject.put("number", ++countNumber);
                jsonObject.put("Action", "sayhello+name");
            }
            return jsonObject;
        }
    
        @PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_NORMAL')")
        @ResponseBody
        @RequestMapping("/goodbye/{name}")
        public JSONObject thirdAction(@PathVariable("name")String name){
            if(name==null)
                name = "001";
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("Name",name);
            synchronized (countNumber) {
                jsonObject.put("number", ++countNumber);
                jsonObject.put("Action", "goodbyte+name");
            }
            return jsonObject;
        }
    
        @PreAuthorize("hasAnyAuthority('AUTH_PUSH','AUTH_POP')")
        @ResponseBody
        @RequestMapping("/push")
        public JSONObject ForthAction(){
            String name = "Someone";
            if(name==null)
                name = "001";
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("Name",name);
            synchronized (countNumber) {
                jsonObject.put("number", ++countNumber);
                jsonObject.put("Action", "goodbyte+name");
            }
            return jsonObject;
        }
    
    //    @PreAuthorize("hasAnyAuthority('AUTH_POP')")
        @ResponseBody
        @RequestMapping("/pop")
        public JSONObject thirdAction(){
            String name = "a person";
            if(name==null)
                name = "001";
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("Name",name);
            synchronized (countNumber) {
                jsonObject.put("number", ++countNumber);
                jsonObject.put("Action", "goodbyte+name");
            }
            return jsonObject;
        }
    }
    

    SpringSecurity配置类

    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity (prePostEnabled = true)
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private UserDetailsServer userDetailsServer;
        @Override
        protected void configure(HttpSecurity http) throws Exception {
    //        super.configure(http);
            http.authorizeRequests()
                    .antMatchers("/").permitAll()
                    .antMatchers("/sayhello/*").hasAnyRole("ADMIN")
                    .antMatchers("/pop").hasAnyAuthority("AUTH_POP")
    //                .antMatchers("/**").fullyAuthenticated()
    //                .and().httpBasic()
                    .and().logout()
                    .and().rememberMe()
                    .and().formLogin();
        }
    
        @Autowired
        protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    //        super.configure(auth);
    //        auth.inMemoryAuthentication().withUser("cc").password("698d51a19d8a121ce581499d7b701668").accountLocked(true).authorities();
            System.out.println("current this configure auto...");
    
            auth.userDetailsService(userDetailsServer).passwordEncoder(new PasswordEncoder() {
                @Override
                public String encode(CharSequence rawPassword) {
                    return GetMD5(rawPassword.toString());
                }
    
                @Override
                public boolean matches(CharSequence rawPassword, String encodedPassword) {
                    String tpwd = GetMD5(rawPassword.toString());
                    if (tpwd.equals(encodedPassword))
                        return true;
                    else
                        return false;
                }
            });
        }
    
        public static String GetMD5(String token)
        {
            String str=new String();
            MessageDigest md;
            try {
                md = MessageDigest.getInstance("MD5");
                byte[] md5 = md.digest(token.getBytes());
                for(int i=0;i<16;i++)
                {
                    String c=new String();
                    c+=md5[i];
                    int a=0;
                    a= Integer.parseInt(c, 10);
                    String s= Integer.toHexString(a);
                    if(s.length()>2)
                        str+=s.substring(s.length()-2);
                    else if(s.length()==1)
                        str+="0"+s;
                    else
                        str+=s;
                }
                System.out.println(str);
            } catch (NoSuchAlgorithmException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return str;
        }
    }
    

    UserDetailsService用户权限验证业务类

    @Service
    public class UserDetailsServer implements UserDetailsService {
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            if(username.equals("aa")) {
                List<GrantedAuthority> grantedAuthorities = new LinkedList<>();
                ((LinkedList<GrantedAuthority>) grantedAuthorities).offer(new SimpleGrantedAuthority("ROLE_ADMIN"));
                return new org.springframework.security.core.userdetails.User(username, "698d51a19d8a121ce581499d7b701668", grantedAuthorities);
            } else if (username.equals("bb")) {
                List<GrantedAuthority> grantedAuthorities = new LinkedList<>();
                ((LinkedList<GrantedAuthority>) grantedAuthorities).offer(new SimpleGrantedAuthority("ROLE_NORMAL"));
                return new org.springframework.security.core.userdetails.User(username, "698d51a19d8a121ce581499d7b701668", grantedAuthorities);
            }else if (username.equals("cc")) {
                List<GrantedAuthority> grantedAuthorities = new LinkedList<>();
                ((LinkedList<GrantedAuthority>) grantedAuthorities).offer(new SimpleGrantedAuthority("AUTH_PUSH"));
                return new org.springframework.security.core.userdetails.User(username, "698d51a19d8a121ce581499d7b701668", grantedAuthorities);
            }else if (username.equals("dd")) {
                List<GrantedAuthority> grantedAuthorities = new LinkedList<>();
                ((LinkedList<GrantedAuthority>) grantedAuthorities).offer(new SimpleGrantedAuthority("AUTH_PUSH"));
                ((LinkedList<GrantedAuthority>) grantedAuthorities).offer(new SimpleGrantedAuthority("AUTH_POP"));
                return new org.springframework.security.core.userdetails.User(username, "698d51a19d8a121ce581499d7b701668", grantedAuthorities);
            }
            return null;
        }
    }
    

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    动态给用户增删权限

    第一步 在UserDetailsService类的loadUserByUsername里
    把用户在数据库里的Role或者Authority全部放到
    GrantedAuthorities 里(Role和Authority可以是多个)
    第二步 写个增删用户 角色/权限表的 Dao,这样就可以动态的给用户增删权限了。

    登录的Remember-Me功能

    SpringSecurity是自带这个功能的,默认关闭;
    需要打开在configure方法里使用
    http.rememberMe();

    实现逻辑这这样的:
    在登录时选择remember-me会在cookie里设置一个key为rememeber-me的元素,默认过期时间为14天,token为用户名和密码的组合加密生成的。服务端也会把这个token存一份,这样在下次游览器与服务连接时会比照下客户端和服务端的token,有相同的就实现了一定时间免登录了。

    一种企业级实现更细粒度权限设计的方案

    集团化的企业和连锁性的店面需要定义某个店铺的职工在拥有对应角色权限的同时只对所在店有操作授权,而且要是集团中心员工权限涵盖整个集团。

    在基础RBAC模型的基础上再 用户表 里定义一个表示所在店面的字段比如 plant .
    可以使用AOP做个before切点做个用户所属店面的判断拦截不具有此店面操作的职工进行操作。

    使用SpringSecurity可以很快捷的实现各种权限系统,在基于Role和Authority两种验证授权的方式下灵活应对各种业务需求。

    游览器禁用了cookie的解决方法

    如果浏览器端拒绝存储cookie信息,就会导致JSESSIONID的值不能正常到达客户端,
    那么客户端向服务器发送请求时,就无法将JSESSIONID的值带回到服务器中,从而导致找不到自己的会话Session
    我们可以使用URL地址重写的办法解决HttpServletResponse encodeURL()和 encodeRedirectURL() 。
    因为cookie在客户端只允许存储4k的数据,那么实际上cookie存储了3k数据就已经到达了一个极限了,cookie就会显得力不从心了,
    所以在B/S交互中就需要一个更大的存储数据对象,这就是session存在的重要起因。
    如果浏览器不支持Cookie,这些函数将重写您的网址以包含会话信息。根据您使用的Java Web框架,这些函数可能会自动调用(只要使用框架的方法编写URL)。
    请注意,在所有情况下都不是所希望的,因为使得会话ID在链接中可见的安全性和缓存影响。 此页面在这个短小的空间中比我可以更好地总结出问题,并提供了禁用此功能的方式。

    展开全文
  • 分享一个大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到人工智能的队伍中来!... saas平台由于其本身“按需购买”...作为一个B端平台型产品,系统权限设计是其中一个非常重要的组成部...

    分享一个大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到人工智能的队伍中来!点击浏览教程 

    saas平台由于其本身“按需购买”的特性,在设计规划权限时,需要考虑统一配置权限如何规避企业没有购买的应用,以及如有部分应用存在数据权限不同的问题。现在,本文简单总结一下当前saas模式下权限的几种设计方式。

    作为一个B端平台型产品,系统的权限设计是其中一个非常重要的组成部分,没有权限管理的系统仿佛一个没有门的房子,任何人都可以随意查看甚至调整,对系统的安全性存在非常大的隐患,而saas模式下由于应用基本独立,随时可能被企业拆分使用。这里权限的统一与拆分问题也十分重要,本文简单总结一下当前saas模式下权限的几种设计方式。

    一、权限管理的重要性

    权限管理一般指根据系统设置的安全规则或者安全策略,用户可以访问而且只能访问自己被授权的资源,权限管理基本是任何一个系统的标配模块。它的作用不仅在于保护系统数据安全性、防止留下系统漏洞,更能在庞大的系统下进行模块和数据配置,让不同的角色进入系统看到不同的模块和数据,最大程度地提高系统的易用性。大部分系统中权限管理是作为一个独立的管理入口,统一设置所有的业务的权限。而saas平台由于其本身“按需购买”的特性,在设计规划权限时,需要考虑统一配置权限如何规避企业没有购买的应用,以及如有部分应用存在数据权限不同的问题。

    二、抽象权限组成

    权限到底是名词属性还是动词属性,还是名词、动词属性均包含,这对于权限的含义很重要。如果是名词属性的话,那么它应该是有具体的指代物;如果是动词,则应该具有行为表示。

    • 权限的名词属性:api接口、页面、功能点。
    • 权限的动词属性:可操作、不可操作。

    那么我们现在来看,其实权限是名词、动词属性,它一定是表达了两层含义。即控制的对象、操作。向上引申可将权限划分为3个组成部分:

    1. 页面权限:用户可以看到那些页面;
    2. 操作权限:用户可以在页面内进行那些操作,增删改查等;
    3. 数据权限:用户可以看到那些数据或内容;

    三、常见的权限控制模型

    (1)自主访问控制(DAC:Discretionary Access Control)

    系统会识别用户,然后根据被操作对象(object)的权限控制列表(ACL:Access Control List)或者权限控制矩阵(ACL:Access Control Matrix)的信息来决定用户的是否能对其进行哪些操作,例如读取或修改。而拥有对象权限的用户,又可以将该对象的权限分配给其他用户,所以称之为“自主(Discretionary)”控制。DAC最大缺陷就是所有用户的权限不能统一管理,用户和用户的权限比较分散,后期调整只能单个进行调整,不易维护。

    (2)强制访问控制(MAC:Mandatory Access Control)

    在MAC的设计中,每一个对象都都有一些权限标识,每个用户同样也会有一些权限标识,而用户能否对该对象进行操作取决于双方的权限标识的关系,这个限制判断通常是由系统硬性限制且无法回避的。强制访问控制多应用于对安全性要求比较高的系统,如多级安全军事系统;

    (3)基于角色的访问控制(RBAC:Role-Based Access Control)

    RBAC是我们当前使用范围最广的一种权限设计模型,模型基础就是用户和角色,角色和权限做多对多的对应。标准的RBAC模型包括四个部件模型,分别为基本模型RABC0、角色分级模型RABC1、角色限制模型RABC2、统一模型RABC3。

    1. RBAC0(基本模型)定义了完全支持RBAC概念的任何系统的最低需求。RBAC0的模型中包括用户(U)、角色(R)和许可权(P)等3类实体集合,RABC0是权限管理的核心部分,其他的版本都是建立在0的基础上。
    2. RBAC1(角色分级模型)基于RBAC0模型,引入角色间的继承关系,即角色上有了上下级的区别,角色间的继承关系可分为一般继承关系和受限继承关系。一般继承关系仅要求角色继承关系是一个绝对偏序关系,允许角色间的多继承。而受限继承关系则进一步要求角色继承关系是一个树结构,实现角色间的单继承。这种模型合适于角色之间的层次明确,包含明确。
    3. RBAC2(角色限制模型)引入了角色间的约束关系,主要约束规则包括:角色间的互斥关系,在处理用户和这些角色之间的关系时,包括静态分离和动态分离,静态分离指互斥的角色不能同时赋予同一个用户;动态分离指用户不能同时操作两个互斥的角色进行登录。
    4. RBAC3(统一模型)同时包含了1和2的特性。

    总结:SAAS后台权限设计案例分析

    如图所示,每个用户关联一个或多个角色,每个角色关联一个或多个权限,从而可以实现了非常灵活的权限管理。角色可以根据实际业务需求灵活创建,这样就省去了每新增一个用户就要关联一遍所有权限的麻烦。简单来说RBAC就是:用户关联角色,角色关联权限。并且在产品和数据设计层面,有更好的扩展性,可控制到任意的粒度。

    (4)基于属性的权限验证(ABAC:Attribute-Based Access Control)

    ABAC则是通过动态计算一个或一组属性,来是否满足某种条件来进行授权判断(可以编写简单的逻辑)。属性通常来说分为四类:用户属性(如用户年龄),环境属性(如当前时间),操作属性(如读取)和对象属性(如一篇文章,又称资源属性),所以理论上能够实现非常灵活的权限控制,几乎能满足所有类型的需求。该设计过于复杂,暂未参透。

    四、基于RBAC权限模型的SAAS平台权限系统设计

    对于SAAS平台这样庞大复杂的平台来说,权限系统设计得越全面、精细、后期的系统扩展性就越高,所以这里采用RBAC权限模型,RBAC权限模型是现有比在这方面比较成熟的权限设计模型,应用这个模型能解决常规的系统权限配置问题,其基本原理也能适用于平台权限设计。

    RBAC对权限抽象概括:判断【Who是否可以对What进行How的访问操作(Operator)】

    RBAC支持三个著名的安全原则:最小权限原则,责任分离原则和数据抽象原则。

    1. 最小权限原则之所以被RBAC所支持,是因为RBAC可以将其角色配置成其完成任务所需要的最小的权限集。
    2. 责任分离原则可以通过调用相互独立互斥的角色来共同完成敏感的任务而体现,比如要求一个计帐员和财务管理员共参与同一过帐。
    3. 数据抽象可以通过权限的抽象来体现,如财务操作用借款、存款等抽象权限,而不用操作系统提供的典型的读、写、执行权限。然而这些原则必须通过RBAC各部件的详细配置才能得以体现。

    ——来自百度百科

    以某物业公司内部信息平台为例,该物业公司平台分为客户档案、房产档案、收费系统、客服工单等多应用结构,其中物业公司组织架构为多层级,基本样式如下如。

    总结:SAAS后台权限设计案例分析

    组织架构

    总结:SAAS后台权限设计案例分析

    应用入口

    总结:SAAS后台权限设计案例分析

    功能页面,以上我们可以将:

    • 组织架构=数据权限
    • 应用入口以及应用菜单=页面权限
    • 功能操作点=操作权限

    1. 基本模型:RBAC0

    抽取角色,建立角色与用户的关系。这里的角色主要是指在组织内承担特定的业务活动,并和别的业务角色进行交互的业务角色。业务角色的抽取主要有两种方式:一种是直接和岗位对应,另外一种是根据流程的本质和需要定义角色。确定各角色的用例图,如下图(简单示例):

    总结:SAAS后台权限设计案例分析

    根据业务复杂度、用户特点进行原型草图设计,在进行权限分配时,可以从增加角色维度以及增加用户维度。如下图:

    总结:SAAS后台权限设计案例分析

    新建角色维度

    总结:SAAS后台权限设计案例分析

    新建用户维度。使用此模型时,我们需要注意的问题有:

    1. 用户和角色为多对一的关系,如果需要用到多对多的关系,将涉及到角色关系的处理,此模型并不适用。
    2. 权限一定是动态可配置的,不是静态的,这点一定要在着手开发前进行说明,一般情况,权限的数据结构为树形,合理的数据结构,便于前端根据实际需求进行解析;
    3. 人员在选择角色获取到对应的权限数据后,最好可以提供一个二次编辑界面,权限会更加灵活。

    2. 角色分级模型:RBAC1

    RBAC1基于RBAC0模型,引入角色间的继承关系,即角色上有了上下级的区别,角色分级模型适用于平台业务功能较多,单个角色设置操作过于繁琐,引用角色分级,可让角色之间存在继承或被继承的关系,比如客服主管可直拥有下级所有员工拥有的权限。建立角色管理,确定角色跟用户之间的关系。(要求角色间有明显的层级关系,所以在没有其他需求的情况下,这里根据业务部门和岗位进行角色的抽取)

    建立角色层级关系和继承关系。

    总结:SAAS后台权限设计案例分析

    角色层级关系

    总结:SAAS后台权限设计案例分析

    一般继承关系

    总结:SAAS后台权限设计案例分析

    受限继承关系

    给角色赋予权限(应用入口权限——应用页面权限、应用页面中操作功能权限、数据查看权限。)权限赋予同RBAC0。增加一个角色管理。如下图:

    总结:SAAS后台权限设计案例分析

    通过角色管理即可以将下级角色的权限直接赋值给上级权限,但由于低级角色的权限全部被高级角色继承,就会导致没有自己角色的私有权限;也可以为人员提供一个二次编辑权限界面,但是一旦编辑后,若后续所属角色权限发生变化,会直接覆盖原有编辑后的权限。

    3. 角色限制模型:RBAC2

    RBAC2,它是RBAC的约束模型,RBAC2也是建立的RBAC0的基础之上的,在RBAC0基础上假如了约束的概念,主要引入了静态职责分离SSD(Static Separation of Duty)和动态职责分离DSD(Dynamic Separation of Duty)。SSD是用户和角色的指派阶段加入的,主要是对用户和角色有如下约束:

    1. 互斥角色:同一个用户在两个互斥角色中只能选择一个;
    2. 基数约束:一个用户拥有的角色是有限的,一个角色拥有的许可也是有限的;
    3. 先决条件约束:用户想要获得高级角色,首先必须拥有低级角色。

    DSD是会话和角色之间的约束,可以动态的约束用户拥有的角色,如一个用户可以拥有两个角色,但是运行时只能激活一个角色。

    总结:SAAS后台权限设计案例分析

    角色权限配置界面可参照RBAC0。用户在配置角色或角色下新建添加用户时,需要根据用户已有的角色身份进行判断。示例:用户A配置角色为客服组长,则可继续添加角色为客服主管,若客服主管已被分配给他人,则也不能分配给用户A(遵从最大拥有数原则)。若同时将保安主管分派至用户A,则操作时,需要选择操作角色。

    总结:SAAS后台权限设计案例分析

    当一个用户配置了多个角色身份时,权限取并集。

    4. 统一模型:RBAC3

    统一模型是包括了继承和分离两种情况的更为复杂的模型,即既要定义角色间的的继承关系,也要维护好角色间的责任分离关系。在这里就不做过多的赘述(两张图供大家参考),因为只要维护好了角色间的约束关系,其他规则类的处理方式同RABC1和RABC2。

    总结:SAAS后台权限设计案例分析

    角色管理

    总结:SAAS后台权限设计案例分析

    权限配置

    五、总结

    1. 角色数据权限

    1. 不同的角色身份查看的角色数据时不相同的,比如物业分公司中深圳区域分公司的管理人员可能就无法管理长沙区域分公司,在给角色分配数据权限时就可以将长沙区域分公司去除。
    2. 除数据权限外,我们还会遇到字段权限,比如:分公司C和分公司D都能看到上海区域分公司的客户情况,但是C看不到客户联系方式,D则能看到联系方式。如果有需要对字段权限进行控制,则可以在设置角色的数据权限或者功能权限时,进行控制。
    3. 题前有提到针对saas模式,可能存在一个角色在管理A跟B应用时可操作的数据权限时不一样的,可以在数据权限中增加一个高级设置权限,为不同的角色针对不用的应用进行分配数据操作。

    2. 用户操作体验

    平台类或者TO B内部产品,虽然不像C端为了留住用户追求极致用户体验,但是也需要确保在交互以及文字理解上面不会让用户产生疑惑情绪,培训成本也是开发成本的一环,尤其针对权限一块可能涉及业务功能复杂,如果在文字描述以及操作上在加大操作难度,可能无法估量的后果。

    3. 默认账号以及默认权限的设置

    对于ToB类或者平台类的产品,正常来讲都会有一个默认的超级管理员的角色以及角色对应的账号,否则系统内第一个角色谁来添加?默认权限的设置则根据需要进行设置,如果是不必要进行控制的权限,当然是可以设置为默认权限的。

    综上所述,根据以上的设计模式以及解决方案,已经能实现大部分企业90%的问题了,实际上很多企业并不需要做到这么小粒度的权限控制。

    展开全文
  • 基于RBAC模型权限设计:如何设计系统权限体系?基于RBAC模型权限设计:如何设计系统权限体系?基于RBAC模型权限设计:如何设计系统权限体系?
  • 在用户登陆时,系统识别用户,根据被操作对象(Subject)的权限控制列表(ACL: Access Control List)或者权限控制矩阵(ACL: AccessControl Matrix)信息设置用户能对哪些操作对象进行何种操作,例读取操作...

    自主访问控制(DAC: Discretionary Access Control)

     

    自主访问控制中,产品中的操作对象被设置了权限等级。

     

    在用户登陆时,系统识别用户,根据被操作对象(Subject)的权限控制列表(ACL: Access Control List)或者权限控制矩阵(ACL: AccessControl Matrix)信息设置用户能对哪些操作对象进行何种操作,例读取操作或能够修改操作对象。

     

    更具特点的是,拥有对象权限的用户,还可以将对象权限分配给其他用户,所以叫“自主(Discretionary)”控制。

     

    Windows中的文档系统的权限设计就是“自主访问控制”模型的典型应用。

     

     

    Windows的文件权限

     

    然而DAC最大缺陷是权限控制分散,不便于管理。例如在文档权限管理中,我们无法将一组文件设置成统一权限开放给指定的一群用户。

     

    强制访问控制(MAC: Mandatory Access Control)

     

    MAC弥补DAC权限控制过于分散的问题。

     

    MAC设计中所有的访问控制策略都由系统管理员来制定,用户无法改变。每个对象都有权限标识,每个用户也会有权限标识,用户能否操作某个对象判断在于两个权限标识的关系,而关系判断通常由系统做硬性限制。

     

    如:用户甲查看文档A,此时系统给出这样的提示“无法访问,需要一级许可”,这说明文档本身有“一级许可”的权限标识,而用户权限不具备。

     

    MAC一般会给用户和资源进行分级,比如:

     

    用户级别:高级,中级,普通

    文件级别:绝密,保密,公开

     

    由系统管理员会制定访问策略,比如高级用户可以访问所有类型的文件,中级用户可以访问保密级别以下的文件,而普通用户只能访问公开的文件。

     

    一般强制访问控制采用以下几种方法:

     

    (1)限制访问控制

    一个持洛伊木马可以攻破任何形式的自主访问控制,由于自主控制方式允许用户程序来修改他拥有文件的存取控制表,因而为非法者带来可乘之机。

     

    MAC不提供这一方便,在这类系统中,用户要修改存取控制表的唯一途径是请求一个特权系统调用。该调用的功能是依据用户终端输入的信息,而不是靠另一个程序提供的信息来修改存取控制信息。

     

    (2)过程控制

    在通常的计算机系统中,只要系统允许用户自己编程,就没办法杜绝木马。但可以对其过程采取某些措施,这种方法称为过程控制。

     

    例如,警告用户不要运行系统目录以外的任何程序。提醒用户注意,如果偶然调用一个其它目录的文件时,不要做任何动作,等等。需要说明的一点是,这些限制取决于用户本身执行与否。

     

    (3)系统限制

    对系统的功能实施一些限制。

     

    比如,限制共享文件,但共享文件是计算机系统的优点,所以是不可能加以完全限制的。再者,就是限制用户编程。不过这种做法只适用于某些专用系统。在大型的,通用系统中,编程能力是不可能去除的。

     

    MAC适用在对保密性要求比较高的系统中,比如军方机构。商业系统中使用MAC的有SE Linux和Trusted Solaris。而对于大部分的商业服务型系统来说,略显死死板不够灵活。

     

    下次我们将继续讲解权限系统的设计细节,请持续关注哦~ 

    展开全文
  • 权限系统与RBAC模型概述[绝对经典]

    万次阅读 多人点赞 2017-06-30 10:12:38
    0. 前言 一年前,我负责的一个项目中需要权限管理。当时凭着自己的逻辑设计出了一套权限管理模型,基本原理与RBAC非常相似,只是过于简陋。当时google了一些权限管理的资料,从中了解到...1. 权限系统与RBAC模型概述
  • RBAC权限系统设计

    千次阅读 2019-06-17 21:52:26
    最近看了很多关于权限管理系统的产品设计的文章(RBAC模型,Role-Based Access Control 基于角色的访问控制),总结下自己认识的权限系统。 一、RBAC模型解释 先来look下图, 图意:通过角色关联用户,角色关联...
  • 权限系统与RBAC模型

    万次阅读 2019-09-28 11:53:12
    系统与 RBAC 模型概述、RBAC 模型简述和实用的 RBAC 模型的数据库建模
  • 最全的权限系统设计

    千次阅读 多人点赞 2020-03-22 20:47:53
    权限管理是公司数据安全的重要保证,针对不同的岗位,不同的级别看到的数据是不一样的,操作数据的限制也是不一样的。...本文会详细介绍权限设计模型,使用本文中的模型基本可以解决所有的权限问题
  • 基于RBAC模型的通用权限管理系统设计(数据模型)
  • 13 简单的设计模型... 24 复杂权限模型:引入Role. 25 复杂用户业务模型:引入Group. 26 关于细粒度的权限控制... 37 权限系统的协作图... 48 从重用的角度分析... 59 跨越问题域重用性解决方案:引入Domain. 510 ...
  • 基于RBAC模型的通用权限管理系统设计
  • RBAC权限系统分析设计与实现

    万次阅读 2019-06-28 09:15:35
    目前,使用最普遍的权限管理模型正是RBAC(Role-Based Access Control)模型,这篇文章也主要是介绍基于RBAC的权限管理系统,我会从RBAC是什么、如何设计RBAC两部分来介绍。 一、RBAC是什么 1、RBAC模型概述 RBAC...
  • 权限系统设计

    千次阅读 2018-11-06 14:06:56
    导读   DMP作为一个大数据管理平台,使用平台的人员众多,使用DMP...DMP系统提供的强大的权限系统来灵活的给使用者分配角色,安全高效的使用DMP。 1.简谈原理  谈到权限控制的设计,需要先理清楚定义和原理。...
  • 超级全面的权限系统设计方案

    千次阅读 2019-09-23 10:18:44
    权限系统设计 前言 权限管理是所有后台系统的都会涉及的一个重要组成部分,主要目的是对不同的人访问资源进行权限的控制,避免因权限控制缺失或操作不当引发的风险问题,如操作错误,隐私数据泄露等问题。 目前在...
  • 13 简单的设计模型... 24 复杂权限模型:引入Role. 25 复杂用户业务模型:引入Group. 26 关于细粒度的权限控制... 37 权限系统的协作图... 48 从重用的角度分析... 59 跨越问题域重用性解决方案:引入Domain. 510 ...
  • 权限系统与RBAC模型概述

    千次阅读 2017-07-21 23:02:35
    0. 前言 一年前,我负责的一个项目中需要权限管理。当时凭着自己的逻辑设计出了一套权限管理模型,基本原理与RBAC非常相似,只是过于简陋。当时google了一些权限管理的资料,从中了解到...1. 权限系统与RBAC模型概述
  • 基于RBAC的权限设计模型

    千次阅读 2013-02-18 17:03:51
    基于RBAC的权限设计模型:   1 RBAC 介绍 RBAC 模型作为目前最为广泛接受的权限模型。 NIST (The National Institute of Standards and Technology,美国国家标准与技术研究院)标准RBAC模型由4个...
  • 组织机构权限系统设计

    千次阅读 2016-09-20 13:53:19
    工作流管理系统中,业务流程的流转,每个节点的... 在工作流管理系统中,企业的组织是系统执行活动和完成任务的载体,组织机构反映了企业人员的管理层次,同时也反映了人与工作,责任权限之间的关系。因此组织机构权限
  • 基于RBAC模型的权限管理系统...介绍了采用的J2EE架构的多层体系结构设计,阐述了基于角色的访问控制RBAC模型的设计思想,并讨论了权限管理系统的核心面向对象设计模型,以及权限访问、权限控制和权限存储机制等关键技术
  •  权限管理,一般指根据系统设置的安全规则或者安全策略,用户可以访问而且只能访问自己被授权的资源,不多不少。  权限管理几乎出现在任何系统里面,只要有用户和密码的系统。 很多人常将“用户身份认证”、...
  • RBAC角色权限模型设计

    千次阅读 2008-03-28 10:55:00
    关于网站用户权限管理的设计模型。我根据业内的一些标准和案例整理出一套RBAC用户权限设计模型文档。希望对大家在系统设计时有帮助。有其他见解请指教。RBAC权限模型设计 在 RBAC社区的不断努力下,RBAC在 2004年 2...
  • BRAC模型 权限设计

    千次阅读 2018-05-21 10:31:41
    在BRAC模型中,涉及到的关键元素有: 用户:系统的使用用户 角色 :拥有相同的权限用户 权限系统可以被用户操作的元素(如:菜单,超链接)以上元素的关系: 用户和角色是多对多的关系; 角色和权限是多对多的...
  • 权限设计-系统登录用户权限设计

    万次阅读 多人点赞 2018-01-08 09:56:06
    需求分析—场景 假设需要为公司设计一个人员管理系统,并为各级领导及全体员工分配系统登录账号。有如下几个要求: 1. 权限等级不同:公司领导登录后可查看所有员工信息,部门领导登录后只可查看本部门员工的...
  • 基于RBAC的saas权限系统设计

    万次阅读 2016-07-21 14:43:00
    在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。在一个组织中,角色是为了完成各种工作而创造,用户则依据它的责任和资格来被指派相

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 127,445
精华内容 50,978
关键字:

权限系统设计模型分析