对于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安全访问: 掌握基于注解的方法,以 ...
随机推荐
- windows 10 启动修复无法自动修复此计算机
1. 失败后有两个选项卡:关机和高级选项,选择高级选项 2. 然后选择疑难解答 3. 选择高级选项 4. 选择回退到以前的版本 接下来需要登录,选择恢复到上一次正常启动的状态,注意选择保留数据,会有提 ...
- Arduino - 串口操作函数与示例代码大全
来源:https://blog.csdn.net/iracer/article/details/50334041 Arduino - 串口操作函数与示例代码大全 本文总结了Arduino常用串口操作函 ...
- matlab中upper 将字符串转换为大写
参考:https://ww2.mathworks.cn/help/matlab/ref/fprintf.html?searchHighlight=fprintf&s_tid=doc_srcht ...
- golang常用库:配置文件解析库-viper使用
一.viper简介 viper 配置解析库,是由大神 Steve Francia 开发,他在google领导着 golang 的产品开发,他也是 gohugo.io 的创始人之一,命令行解析库 cob ...
- background-size 详解
backgroun-size:cover; .是按照等比缩放铺满整个区域.主要用于图片比div小的时候,将图片按照某一边的比例扩大以填充整个div背景. .优点:图片不会被拉升,且实用于div长度和宽 ...
- 多测师_高级讲师肖sir讲解html中 Button跳转连接方法归纳
第一种方法: 1.1<a href="http://www.baidu.com"> <input type="button" name=& ...
- CentOS 7系统常见快捷键操作方式
快捷键操作方式 Linux系统中一些常见的快捷方式,可有效提高操作效率,在某些时刻也能避免操作失误带来的问题. 最有用的快捷键 序号 快捷键 官方说明 掌握程度 01 Tab 命令或路径等的补全键 移 ...
- QJsonObject 遍历
遍历QjsonObject方式 方式一 QJsonObject::const_iterator it = l_obj.constBegin(); QJsonObject::const_iterator ...
- 【应用服务 App Service】当使用EntityFrameWorkCore访问Sql Server数据库时,在Azure App Service会出现Cannot create a DbSet for ** because this type is not included in the model for the context的错误
问题情形 使用EF Core访问数据库,在本地运行正常,发布到App Service后,偶尔出现了Cannot create a DbSet for ** because this type is n ...
- ubuntu 搭建samba服务器&挂载(mount)代码到本地
一.搭建samba服务器 1.下载: sudo apt-get install samba samba-common 2.创建共享文件夹MyShare: mkdir /home/user/MyShar ...