一、什么是RBAC模型

  RBAC模型是一个解决用户权限问题的设计思维。

  在最简单的RBAC模型中,将用户表设计为如下几个表

  1、用户

  2、角色

  3、权限

  以及这三张表衍生出来的两张中间表

  4、用户_角色表

  5、权限_角色表

  上面描述的5张表就构成了最基本也是最成熟的RBAC模型,可以看得出RBAC模型中的核心是角色,所有与用户相关的权限都是通过角色表进行关联的!在今后我们可能会用到的按钮元素表,样式表等各种各样的资源表最终都如权限表一般,与角色进行关联。RBAC的哲学就是,认角色不认用户,所有的查询都是通过角色来完成的。

1.1、RBAC模型的注意点

  我们之所以要用到RBAC模型,本质上是为了实现两个功能:

  1、资源对用户的可见性,例如:当前用户对应的角色是否能“看到“某个菜单项或是某个按钮,这一部分其实重在前端渲染,资源的可见性并不能保证资源安全,当有心人拿到资源的请求路径时依旧可以发出相应的请求。在我看来,对资源的可见性,更多的是对用户的体验上的优化。

  2、对请求的鉴权,这部分才应该是我们关注的核心点。

  需要注意的是,对于资源可见性的控制上,我们只要简单的将五张表进行关联查询,然后通过foreach渲染出用户可见的按钮即可,没有什么复杂的操作。无论是前后端分离的项目还是,传统项目或是各种模板引擎,都建议这样做,当然了还有别的做法shiro自带了jsp渲染规则,大家看看就好。

  而对请求鉴权时,如果我们通过手写filter就显得极不优雅,不便于维护。所以就需要结合一些权限框架来使用,在项目中我优先推荐使用Apache的shiro。因为大伙都能快速入手,学习曲线平稳,框架灵活又安全。

  在RBAC模型中,整个系统中需要进行鉴权的菜单,按钮,API,其实都是公共的一套,通过鉴权来实现不同角色展示不同的菜单。

二、查询权限列表的思路

  当我们在鉴权的时候,最终都是要查询出一个collection集合,在使用mybatis的时候其实就是通过多表查询出一个collection集合。伪代码如下

  user代表用户表

  role代表角色表

  permission代表权限表

  user_role代表用户角色中间表

  role_permission代表用户权限中间表

1 @Select(select 权限字段名称 from
2 user,user_role,role,role_permission,permission
3 where
4 user.主键 = user_role.用户主键
5 and role.主键 = user_role.角色主键
6 and role.主键 = role_permission.角色主键
7 and permission.主键 = role_permission.权限主键
8 and user.主键 = ?

  这样就可以查询出当前用户包含的所有的权限名称列表,shiro就是通过权限名称来进行鉴权处理的,返回结果最好用Set<String>来接收,一个是为了放置重复,虽然说重复了也没啥,另一个是为了在构造函数中传入set集合。

不过这是角色构建,讲道理在权限这块,大家与查询role套路保持一致能清晰一点点。

三、RBAC怎样与shiro进行集成使用

  我们想要将RBAC与shiro集成使用,需要优先理解,为什么要这样做。

  上面我已经提到了,在对请求进行鉴权的时候,我们碰到了一个小的难题。而shiro自定义realm继承AuthorizingRealm抽象类,就可以优雅的解决请求鉴权。

  这里有一个小彩蛋,我们可以只实现认证的realm,但是在项目中我们肯定要实现授权的realm即AuthorizingRealm,为什么授权的realm中既有认证方法又有授权方法呢?猜测是因为,在shiro中认证是鉴权的前置条件(其实好像在任何情况下都是这样,不进行认证我都不知道用户身份那么何谈鉴权---确定当前身份有什么样的权限嘞),所以shiro在实现鉴权realm时,并不需要继承认证的自定义realm。  具体要怎么做的?  其实套路很简单,就是以RABC模型中的角色为桥梁,查出当前用户对应的所有权限,然后将每个url需要的权限进行配置(可以使xml或是@configuration)。再将构造一个SimpleAuthorizationInfo,调用public void addObjectPermissions(Collection<Permission> permissions)  将权限列表设置进当前的角色中。这样就完成了权限的校验。

 1 //这个是shiro框架的基础配置
2 @Configuration
3 public class ShiroConfiguration
4 {
5 //@Bean
6 //public CustomMatcher getCustomMatcher(){
7 // return new CustomMatcher();
8 //}
9
10 //配置自定义的Realm,这个realm是自定义的认证鉴权逻辑
11 @Bean
12 public CustomRealm getRealm()
13 {
14 CustomRealm customRealm = new CustomRealm();
15 //customRealm.setCredentialsMatcher(customMatcher);
16 return customRealm;
17 //在realm中也可以自定义我们的密码校验逻辑,shiro文档搜索 CredentialsMatcher就知道怎么玩了
18 }
19
20 //配置安全管理器
21 @Bean
22 public SecurityManager securityManager(CustomRealm realm) {
23 //使用默认的安全管理器
24 DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(realm);
25 //将自定义的realm交给安全管理器统一调度管理
26 securityManager.setRealm(realm);
27 return securityManager;
28 }
29
30 //Filter工厂,设置对应的过滤条件和跳转条件
31 @Bean
32 public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
33 //1.创建shiro过滤器工厂
34 ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();
35 //2.设置安全管理器
36 filterFactory.setSecurityManager(securityManager); //3.通用配置(配置登录页面,登录成功页面,验证未成功页面)
37 filterFactory.setLoginUrl("/autherror?code=1");
38 //设置登录页面
39 filterFactory.setUnauthorizedUrl("/autherror?code=2");
40 //授权失败跳转页面
41 //4.配置过滤器集合
42 Map<String,String> filterMap = new LinkedHashMap<String,String>();
43 // 配置不会被拦截的链接 顺序判断
44 filterMap.put("/user/home", "anon");
45 filterMap.put("/user/**", "authc");
46
47 //5.设置过滤器
48 filterFactory.setFilterChainDefinitionMap(filterMap); return filterFactory;
49 }
50 }

四、总结

  上面说了这么多,其实需要非常关注的点有两个:

  1、第一就是视图层面我们是通过查库以及渲染规则来完成客户体验层面的鉴权的,这一步无需shiro的介入(当然shiro中也有关于jsp权限渲染的内容,但是不做介绍了,自己查库渲染比使用shiro自带的jsp渲染要思路清晰的多,而且没有技术壁垒,可以用于各种技术中)。

  2、第二点是,在url鉴权时,通过shiro来完成,主要是通过设置filterfactory自定义权限鉴定规则,以及自定义AuthorizingRealm时注入权限列表来完成请求访问层面的鉴权。

对于RBAC与shiro的一些思考的更多相关文章

  1. SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建

    SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建 技术栈 : SpringBoot + shiro + jpa + freemark ,因为篇幅原因,这里只 ...

  2. 一次关于shiro反序列化漏洞的思考

    0x01前言 之前在我反序列化的那篇文章中(https://www.cnblogs.com/lcxblogs/p/13539535.html),简单说了一下反序列化漏洞,也提了一嘴常见的几种Java框 ...

  3. RBAC用户特别授权的思考

    场景: 标准的RBAC,授权只应该赋予角色,再把角色指派给用户,当需要对特定用户授予权限时,就只能新建一个角色指派给这个用户.这就意味着每对一个新用户做特别授权都要创建一个特别角色. 今天脑洞大开,想 ...

  4. 关于Shiro的退出请求是如何关联到登录请求的思考

    一.结论 先给出结论,是因为本身是很简单的道理.假设我们没有使用任何认证授权的框架,就简单的使用Cookie和HttpSession,那么用户登录后的每一个请求是如何关联上这个用户的呢?答案很简单,由 ...

  5. 补习系列(6)- springboot 整合 shiro 一指禅

    目标 了解ApacheShiro是什么,能做什么: 通过QuickStart 代码领会 Shiro的关键概念: 能基于SpringBoot 整合Shiro 实现URL安全访问: 掌握基于注解的方法,以 ...

  6. Shiro权限管理框架详解

    1 权限管理1.1 什么是权限管理 基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被 ...

  7. 权限管理系统(五):RBAC新解,基于资源的权限管理

    本文讨论以角色概念进行的权限管理策略及主要以基于角色的机制进行权限管理是远远不够的.同时我将讨论一种我认为更好的权限管理方式. 1.什么是角色 当说到程序的权限管理时,人们往往想到角色这一概念.角色是 ...

  8. Shiro框架 (原理分析与简单实现)

    Shiro框架(原理分析与简单实现) 有兴趣的同学也可以阅读我之前分享的:Java权限管理(授权与认证)CRM权限管理   (PS : 这篇博客里面的实现方式没有使用框架,完全是手写的授权与认证,可以 ...

  9. SpringBoot 整合Shiro 一指禅

    目标 了解ApacheShiro是什么,能做什么: 通过QuickStart 代码领会 Shiro的关键概念: 能基于SpringBoot 整合Shiro 实现URL安全访问: 掌握基于注解的方法,以 ...

随机推荐

  1. Python之路——变量

    什么是变量 #变量即变化的量,核心是"变"与"量"二字,变即变化,量即衡量状态. 为什么要有变量 #程序执行的本质就是一系列状态的变化,变是程序执行的直接体现, ...

  2. Word云(标签云)生成器控件。net Windows。形式在c#中

    下载demo - 37.1 KB 下载source code - 48.7 KB 背景 这种控制方式的灵感来自于一种名为Wordle的基于网络的免费单词云生成器.实际上,这个控件是我的项目http:/ ...

  3. Docker笔记4:在 CentOS 上安装 Docker

    Docker 是一个开源的应用容器引擎,主要有两个分支,一个是社区免费版(Docker CE),一个是企业版(Docker EE). 第1步:系统环境要求 Docker 支持的 CentOS 版本: ...

  4. Python基本语法之数据类型(总览)

    Python的八种数据类型 Number,数值类型 String,字符串,主要用于描述文本 List,列表,一个包含元素的序列 Tuple,元组,和列表类似,但其是不可变的 Set,一个包含元素的集合 ...

  5. 多测师讲解自动化 _rf 变量_高级讲师肖sir

    rf变量 log 打印全局变量 列表变量: 字典变量: 查看当前工程下的变量 紫色表示变量名有误 设置全局变量 设置列表变量 设置字段变量 关键字书写格式问题

  6. Rust之路(4)——所有权

    [未经书面同意,严禁转载] -- 2020-10-14 -- 所有权是Rust的重中之重(这口气咋像高中数学老师 WTF......). 所有权是指的对内存实际存储的数据的访问权(包括读取和修改),在 ...

  7. 数据查询语句:DQL(Data Query Language)

    一.基础查询 1.语法:select 查询列表 from 表名; 2.特点:1.通过select查询完的结果,是一个虚拟的表格,不是真实存在   2.查询列表可以是:字段.表达式.常量.函数等   3 ...

  8. linux(centos8):使用namespace做资源隔离

    一,namespace是什么? namespace 是 Linux 内核用来隔离内核资源的方式. 它是对全局系统资源的封装隔离, 处于不同 namespace 的进程拥有独立的全局系统资源, 改变一个 ...

  9. HTML <del> 标签

    HTML <del> 标签 什么是<del> 标签? 定义文档中已被删除的文本. 实例 a month  is <del>25</del> 30 day ...

  10. python 实现多层列表拆分成单层列表

    有个多层列表:[1, 2, 3, 4, [5, 6, [7, 8]], ['a', 'b', [2, 4]]],拆分成单层列表 使用内置方法 结果和原列表顺序不同 def split(li): pop ...