对于RBAC与shiro的一些思考
一、什么是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的一些思考的更多相关文章
- SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建
SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建 技术栈 : SpringBoot + shiro + jpa + freemark ,因为篇幅原因,这里只 ...
- 一次关于shiro反序列化漏洞的思考
0x01前言 之前在我反序列化的那篇文章中(https://www.cnblogs.com/lcxblogs/p/13539535.html),简单说了一下反序列化漏洞,也提了一嘴常见的几种Java框 ...
- RBAC用户特别授权的思考
场景: 标准的RBAC,授权只应该赋予角色,再把角色指派给用户,当需要对特定用户授予权限时,就只能新建一个角色指派给这个用户.这就意味着每对一个新用户做特别授权都要创建一个特别角色. 今天脑洞大开,想 ...
- 关于Shiro的退出请求是如何关联到登录请求的思考
一.结论 先给出结论,是因为本身是很简单的道理.假设我们没有使用任何认证授权的框架,就简单的使用Cookie和HttpSession,那么用户登录后的每一个请求是如何关联上这个用户的呢?答案很简单,由 ...
- 补习系列(6)- springboot 整合 shiro 一指禅
目标 了解ApacheShiro是什么,能做什么: 通过QuickStart 代码领会 Shiro的关键概念: 能基于SpringBoot 整合Shiro 实现URL安全访问: 掌握基于注解的方法,以 ...
- Shiro权限管理框架详解
1 权限管理1.1 什么是权限管理 基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被 ...
- 权限管理系统(五):RBAC新解,基于资源的权限管理
本文讨论以角色概念进行的权限管理策略及主要以基于角色的机制进行权限管理是远远不够的.同时我将讨论一种我认为更好的权限管理方式. 1.什么是角色 当说到程序的权限管理时,人们往往想到角色这一概念.角色是 ...
- Shiro框架 (原理分析与简单实现)
Shiro框架(原理分析与简单实现) 有兴趣的同学也可以阅读我之前分享的:Java权限管理(授权与认证)CRM权限管理 (PS : 这篇博客里面的实现方式没有使用框架,完全是手写的授权与认证,可以 ...
- SpringBoot 整合Shiro 一指禅
目标 了解ApacheShiro是什么,能做什么: 通过QuickStart 代码领会 Shiro的关键概念: 能基于SpringBoot 整合Shiro 实现URL安全访问: 掌握基于注解的方法,以 ...
随机推荐
- 数论(8):min_25 筛(扩展埃氏筛)
min_25 筛介绍 我们考虑这样一个问题. \[ans=\sum_{i = 1}^nf(i)\\ \] 其中 \(1 \le n \le 10^{10}\) 其中 \(f(i)\) 是一个奇怪的函数 ...
- heap是堆,stack是栈
1.栈是用来存放基本类型的变量和引用类型的变量,堆用来存放new出来的对象和数组. 2.栈的存取速度快,但不灵活.堆的存取速度慢,但是存取灵活,空间动态分配. 3.栈在建立在连续的物理位置上,而堆只需 ...
- vue中,使用 es6的 ` 符号给字符串之间换行
我这里分功能是点击"复制范围",就相当于复制图上的坐标点一样的数据和格式: "复制功能"的代码如下: copyPoints() { const vm = thi ...
- 优质分享 | Spring Boot 入门到放弃!!!
持续原创输出,点击上方蓝字关注我 目录 前言 视频目录 如何获取? 总结 前言 最近不知不觉写Spring Boot专栏已经写了九篇文章了,从最底层的项目搭建到源码解析以及高级整合的部分,作者一直在精 ...
- 联赛模拟测试14 A. 虎
题目描述 这题太虎了,所以没有背景. 给你一棵树,边有黑白两种颜色,你每次可以选择两个点,把这两个点之间的唯一简单路径上的所有边颜色取反,某些边要求最终颜色必须是黑色,还有些边没有要求,问最少操作多少 ...
- devops-jenkins-Pipeline实战
1) 配置gitlab的分支项目 点击红色标记的创建 project 项目 点击Create project创建Pipeline-demo项目 项目创建完成,然后我们创建一个Add README 然后 ...
- 【数位DP】SCOI2014 方伯伯的商场之旅
题目内容 方伯伯有一天去参加一个商场举办的游戏.商场派了一些工作人员排成一行.每个人面前有几堆石子. 说来也巧,位置在 \(i\) 的人面前的第 \(j\) 堆的石子的数量,刚好是 \(i\) 写成 ...
- go读取键盘输入两种方式
一种scanf var x intfmt.Println("input a int number")fmt.Scan(&x)fmt.Printf("读取到内容:% ...
- spring boot:使用多个线程池实现实现任务的线程池隔离(spring boot 2.3.2)
一,为什么要使用多个线程池? 使用多个线程池,把相同的任务放到同一个线程池中,可以起到隔离的作用,避免有线程出错时影响到其他线程池,例如只有一个线程池时,有两种任务,下单,处理图片,如果线程池被处理图 ...
- centos8平台使用mpstat监控cpu
一,mpstat的用途 mpstat是 Multiprocessor Statistics的缩写,是实时cpu监控工具. 在多CPU系统里,其不但能查看所有CPU的平均状况信息,而且能够查看特定CPU ...