一、什么是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. Java之ConcurrentHashMap源码解析

    ConcurrentHashMap源码解析 目录 ConcurrentHashMap源码解析 jdk8之前的实现原理 jdk8的实现原理 变量解释 初始化 初始化table put操作 hash算法 ...

  2. shell-的变量-局部变量

    1. 定义本地变量 本地变量在用户当前的shell生产期的脚本中使用.例如,本地变量OLDBOY取值为ett098,这个值只在用户当前shell生存期中有意义.如果在shell中启动另一个进程或退出, ...

  3. golang RSA2加密/解密

    $go get github.com/wenzhenxi/gorsa test.go文件的内容 运行: $go run test.go package main import ( "fmt& ...

  4. git 本地回滚到上一个版本

    linux下是 git reset --hard HEAD^ windows下是 git reset --hard HEAD"^"

  5. IDEA设置maven修改settings.xml配置文件无法加载仓库

    作为初学者配置maven一般网上搜索.然后你就看到各种配置文件片段,首先配置镜像,然后配置仓库.完事后再IDEA里面配置下maven的路径和配置文件路径. 这些文章属实坑爹,完全没讲一个重要的配置就是 ...

  6. HTML常用标签(下)

    HTML常用标签(下) 1. 表格标签 1.1 语法 <table> <!--table定义表格--> <tr> <!--tr定义表格中的行--> &l ...

  7. day54 Pyhton 前端JS05

    今日内容: 1.数组Array var colors = ['red','color','yellow']; 使用new 关键词对构造函数进行创建对象 var colors2 = new Array( ...

  8. Jenkins+pytest+Allure搭建自动化测试

    持续集成(CONTINUOUS INTEGRATION) 在CI环境中,开发人员将会频繁地向主干提交代码.这些新提交的代码在最终合并到主干前,需要经过编译和自动化测试流进行验证. 持续交付(CONTI ...

  9. C++ 虚函数简介!程序员必学知识,掌握编程从对象开始!

    本文将简单探究一下 c++ 中的虚函数实现机制.主要基于 vs2013 生成的 32 位代码进行研究,相信其它编译器(比如, gcc )的实现大同小异. 先从对象大小开始 假设我们有如下代码,假设 i ...

  10. spring boot:shardingsphere多数据源,支持未分表的数据源(shardingjdbc 4.1.1)

    一,为什么要给shardingsphere配置多数据源? 1,shardingjdbc默认接管了所有的数据源, 如果我们有多个非分表的库时,则最多只能设置一个为默认数据库, 其他的非分表数据库不能访问 ...