Spring Expression Language(SpEL)实现ABAC鉴权模型, 动态计算实体的属性、操作类型、相关的环境来控制是否有对操作对象的权限

2023-11-13

/**
 * @author changjin wei(魏昌进)
 * @since 2022/11/26
 */

最近有点无聊,以至于我很已经很久没有写出高质量的博客,为了挽回自己的这种无聊感打算手撕一下ABAC模型,毕竟RBAC模型五张基础表玩来玩去也玩不出来多少火花了,整理一下ABAC模型的实现也让这个周末更有意义一点。

第一章ABAC授权模型是为了让大家先理解何为ABAC。
第二章ABAC实践是对ABAC模型的代码实现。
第三章简单的描述了一下如何整合进Spring Security 或者 Apache Shiro。

项目源码:galaxy-sea/galaxy-blogs/code/abac

ABAC授权模型

个人觉得这两篇文章已经完美描述了ABAC模型的原理

常用的授权模型

此节摘自基于属性的访问控制(ABAC)- 阿里云IDaaS

  • ACL(Access Control List),在ACL中,包含用户、资源、资源操作 三个关键要素。通过将资源以及资源操作授权给用户而使用户获取对资源进行操作的权限。

  • RBAC(Role-Based Access Control ),是把用户按角色进行归类,通过用户的角色来确定用户能否针对某项资源进行某项操作。RBAC相对于ACL最大的优势就是它简化了用户与权限的管理,通过对用户进行分类,使得角色与权限关联起来,而用户与权限变成了间接关联。

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

ABAC的访问控制

基于ABAC访问控制需要动态计算实体的属性、操作类型、相关的环境来控制是否有对操作对象的权限,所以在设计的时候需要考虑的条件判断的灵活性、通用性、易用性,用户只需要通过web页面即可配置授权,这需要减少硬编码似得逻辑变得简单通用,那么这需要满足一些运算符来实现。

类型 运算符
算术运算符 +, -, *, /, %, ^, div, mod
关系运算符 <, >, ==, !=, <=, >=, lt, gt, eq, ne, le, ge
逻辑运算符 and, or, not, &&, ||, !
条件 ?:

使用场景

用户只需要配置 user.age > 20 的条件即可获得特定的权限。

表达式语言

正如上一节所说的需要对某种条件进行解析那么就需要表达式语言,这让我想起了Spring Framework@Value注解和MyBatis<if test=“”>

// 相信很多 Java boy都使用过的吧
@Value("A?B:C")
private String A;
<select id = "XXX">
    <if test="user != null">
        XXXX
    </if>
</select>

看到这里大家应该大致猜到了ABAC的的核心就是Expression Language(EL),虽然上面的代码演示是使用Java生态作为演示,但是可以大胆的相信其他的编程语言都是有着自己的EL框架的。

java EL框架列表

  • spring-expression
  • OGNL
  • MVEL
  • JBoss EL

这里就不一一列举了感兴趣可以查看Java EL生态排名

SpEL性能

Spring Expression Language (SpEL)官方文档

// Spring官方文档摘取 翻译
Spring Framework 4.1 包含一个基本的表达式编译器。表达式通常被解释,这在评估期间提供了很多动态灵活性,但没有提供最佳性能。对于偶尔的表达式使用,这很好,但是,当由其他组件(如 Spring Integration)使用时,性能可能非常重要,并且没有真正需要动态性。

SpEL 编译器旨在满足这一需求。在求值期间,编译器生成一个 Java 类,它体现了运行时的表达式行为,并使用该类来实现更快的表达式求值。由于缺少表达式周围的类型,编译器在执行编译时使用在表达式的解释评估期间收集的信息。例如,它不能纯粹从表达式中知道属性引用的类型,但在第一次解释评估期间,它会找出它是什么。当然,如果各种表达式元素的类型随时间发生变化,基于此类派生信息进行编译可能会在以后造成麻烦。出于这个原因,编译最适合其类型信息在重复计算时不会改变的表达式。

考虑以下基本表达式:

someArray[0].someProperty.someOtherProperty < 0.1

由于前面的表达式涉及数组访问、某些属性取消引用和数字操作,因此性能提升非常显着。在一个运行 50000 次迭代的微型基准测试示例中,使用解释器评估需要 75 毫秒,使用表达式的编译版本仅需要 3 毫秒。

有关SpEL的性能Spring官方描述说SpEL的性能很棒(个人感觉Spring对自己的测试结果是不是少打了一个0啊,3ms的时间有点无法理解)

ABAC实践

本章仅实现ABAC的原理,不会对Spring Security和 Apache Shiro做任何的集成

因为笔者本人是一位Spring boy,所以工程项目会以Spring Boot框架作为基础,使用其它编程语言的同学可能需要受苦一下了

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Expression Language(SpEL)实现ABAC鉴权模型, 动态计算实体的属性、操作类型、相关的环境来控制是否有对操作对象的权限 的相关文章

  • Java 枚举与创建位掩码和检查权限的混淆

    我想将此 c 权限模块移植到 java 但是当我无法将数值保存在数据库中然后将其转换为枚举表示形式时 我很困惑如何执行此操作 在 C 中 我创建一个如下所示的枚举 public enum ArticlePermission CanRead
  • org.apache.hadoop.security.AccessControlException:客户端无法通过以下方式进行身份验证:[TOKEN,KERBEROS] 问题

    我正在使用 java 客户端通过 Kerberos 身份验证安全访问 HDFS 我尝试打字klist在服务器上 它显示已经存在的有效票证 我收到的异常是客户端无法通过以下方式进行身份验证 TOKEN KERBEROS 帮助将不胜感激 这是一
  • 如何在 Spring 中禁用使用 @Component 注释创建 bean?

    我的项目中有一些用于重构逻辑的通用接口 它看起来大约是这样的 public interface RefactorAwareEntryPoint default boolean doRefactor if EventLogService wa
  • jQuery AJAX 调用 Java 方法

    使用 jQuery AJAX 我们可以调用特定的 JAVA 方法 例如从 Action 类 该 Java 方法返回的数据将用于填充一些 HTML 代码 请告诉我是否可以使用 jQuery 轻松完成此操作 就像在 DWR 中一样 此外 对于
  • 在 Jar 文件中运行 ANT build.xml 文件

    我需要使用存储在 jar 文件中的 build xml 文件运行 ANT 构建 该 jar 文件在类路径中可用 是否可以在不分解 jar 文件并将 build xml 保存到本地目录的情况下做到这一点 如果是的话我该怎么办呢 Update
  • 谷歌应用程序引擎会话

    什么是java应用程序引擎 默认会话超时 如果我们将会话超时设置为非常非常长的时间 会不会产生不良影响 因为谷歌应用程序引擎会话默认情况下仅存储在数据存储中 就像facebook一样 每次访问该页面时 会话仍然永远存在 默认会话超时设置为
  • Java 集合的并集或交集

    建立并集或交集的最简单方法是什么Set在 Java 中 我见过这个简单问题的一些奇怪的解决方案 例如手动迭代这两个集合 最简单的单行解决方案是这样的 set1 addAll set2 Union set1 retainAll set2 In
  • 从最终实体获取根证书和中间证书

    作为密码学的菜鸟 我每天都会偶然发现一些简单的事情 今天只是那些日子之一 我想用 bouncy castle 库验证 java 中的 smime 消息 我想我几乎已经弄清楚了 但此时的问题是 PKIXparameters 对象的构建 假设我
  • java.lang.IllegalStateException:提交响应后无法调用 sendRedirect()

    这两天我一直在尝试找出问题所在 我在这里读到我应该在代码中添加一个返回 我做到了 但我仍然得到 java lang IllegalStateException Cannot call sendRedirect after the respo
  • 将 MOXy 设置为 JAXB 提供程序,而在同一包中没有属性文件

    我正在尝试使用 MOXy 作为我的 JAXB 提供程序 以便将内容编组 解组到 XML JSON 中 我创建了 jaxb properties 文件 内容如下 javax xml bind context factory org eclip
  • Spring 3 匹配通配符严格,但找不到元素 'jee:jndi-lookup' 的声明

    所以我遇到了与这里类似的问题 Spring 3 0错误 匹配通配符严格 但找不到元素的声明 https stackoverflow com questions 8651781 spring 3 0 error the matching wi
  • 如何访问JAR文件中的Maven资源? [复制]

    这个问题在这里已经有答案了 我有一个使用 Maven 构建的 Java 应用程序 我有一个资源文件夹com pkg resources 我需要从中访问文件 例如directory txt 我一直在查看各种教程和其他答案 但似乎没有一个对我有
  • Java 和 Python 可以在同一个应用程序中共存吗?

    我需要一个 Java 实例直接从 Python 实例数据存储中获取数据 我不知道这是否可能 数据存储是否透明 唯一 或者每个实例 如果它们确实可以共存 都有其单独的数据存储 总结一下 Java 应用程序如何从 Python 应用程序的数据存
  • 尝试将 Web 服务部署到 TomEE 时出现“找不到...的 appInfo”

    我有一个非常简单的项目 用于培训目的 它是一个 RESTful Web 服务 我使用 js css 和 html 创建了一个客户端 我正在尝试将该服务部署到 TomEE 这是我尝试部署时遇到的错误 我在这里做错了什么 刚刚遇到这个问题 我曾
  • 获取文件的总大小(以字节为单位)[重复]

    这个问题在这里已经有答案了 可能的重复 java 高效获取文件大小 https stackoverflow com questions 116574 java get file size efficiently 我有一个名为 filenam
  • 非 Spring 托管类中 DI 的编译时编织

    我想为标记为的类配置编译时编织 Configurable注释能够将 spring 依赖项注入到初始化的类中new操作员 我不想使用加载时编织 因为我无权访问应用程序服务器的运行脚本 因此无法修改它 另外 我希望能够在测试中使用此类 我的意思
  • 干净构建 Java 命令行

    我正在使用命令行编译使用 eclipse 编写的项目 如下所示 javac file java 然后运行 java file args here 我将如何运行干净的构建或编译 每当我重新编译时 除非删除所有内容 否则更改不会受到影响 cla
  • 使用 CXF-RS 组件时,为什么我们使用 而不是普通的

    作为后续这个问题 https stackoverflow com questions 20598199 对于如何正确使用CXF RS组件我还是有点困惑 我很困惑为什么我们需要
  • CamcorderProfile.videoCodec 返回错误值

    根据docs https developer android com reference android media CamcorderProfile html 您可以使用CamcorderProfile获取设备默认视频编解码格式 然后将其
  • 双枢轴快速排序和快速排序有什么区别?

    我以前从未见过双枢轴快速排序 是快速排序的升级版吗 双枢轴快速排序和快速排序有什么区别 我在 Java 文档中找到了这个 排序算法是双枢轴快速排序 作者 弗拉基米尔 雅罗斯拉夫斯基 乔恩 本特利和约书亚 布洛赫 这个算法 在许多数据集上提供

随机推荐