Spring Security 中细化权限粒度的方法

有小伙伴表示微人事(https://github.com/lenve/vhr)的权限粒度不够细。不过松哥想说的是,技术都是相通的,明白了 vhr 中权限管理的原理,在此基础上就可以去细化权限管理粒度,细化过程和还是用的 vhr 中用的技术,只不过设计层面重新规划而已。

当然今天我想说的并不是这个话题,主要是想和大家聊一聊 Spring Security 中权限管理粒度细化的问题。因为这个问题会涉及到不同的权限管理模型,今天和小伙伴们聊一聊~

1.权限管理模型

要想将细化权限粒度,我们不可避免会涉及到一些权限模型,例如 ACL、RBAC、DAC、MAC 以及 ABAC、PBAC 等。

在这些众多的权限模型中,我们使用较多的是 RBAC,ACL 也有一些项目在使用,另外几种则使用相对较少。因此松哥这里重点和大家介绍 ACL 和 RBAC。

1.1 ACL

ACL 是一种比较古老的权限控制模型。英文全称是 Access Control List,中文称作访问控制列表,这是一种面向资源的访问控制模型,所有的权限配置都是针对资源的。

它的原理是这样:

对于系统中的每一个资源,都会配置一个访问列表,这个列表中记录了用户/角色对于资源的 CURD 权限,当系统需要访问这些资源时,会首先检查列表中是否存在当前用户的访问权限,进而确定当前用户是否可以执行相应的操作。

ACL 的使用非常简单,搞明白它的原理自己分分钟就能实现。但是 ACL 有一个明显的缺点,就是需要维护大量的访问权限列表。大量的访问控制列表带来的问题就是性能下降以及维护复杂。

1.2 RBAC

RBAC(Role-based access control)是一种以角色为基础的访问控制,也是目前使用较多的一种权限模型,它有多种不同的变体,松哥后面会专门写一篇文章来介绍 RBAC,这里仅简单科普下。

RBAC 权限模型将用户按角色进行归类,通过用户的角色来确定用户对某项资源是否具备操作权限。RBAC 简化了用户与权限的管理,它将用户与角色关联、角色与权限管理、权限与资源关联,这种模式使得用户的授权管理变得非常简单和易于维护。

1.3 其他

下面这些使用常见较少,小伙伴们做一个了解即可,感兴趣的小伙伴也可以自行研究下。

  • ABAC:这是一种基于属性的访问控制。
  • PBAC:这是一种基于策略的访问控制。
  • DAC:除了权限控制,主体也可以将权限授予其他主体。
  • MAC:资源可以被哪些类别的主体进行哪些操作,主体可以对哪些等级的资源进行哪些操作,这两个条件同时满足时,允许访问。

2.ACL

接下来松哥要和大家仔细介绍一下 ACL 这种权限模型,RBAC 我后面专门写文章介绍,本文先不做讨论。

Acl 的全称是 Access Control List,也就是我们所说的访问控制列表,是用以控制对象的访问权限的。Acl 的一个核心思路就是将某个对象的某种权限授予某个用户或某种角色,它们之间的关系是多对多,即一个用户/角色可以具备某个对象的多种权限,某个对象的权限也可以被多个用户/角色所持有。

举个简单例子:

现在有一个 User 对象,针对该对象有查询、修改、删除等权限,可以将这些权限赋值给某一个用户,也可以将这些权限赋值给某一个角色,当用户具备这些角色时就具有执行相应操作的权限。

从这个角度看,Acl 是一种粒度非常细的权限控制,它就是专门控制某一个对象的操作权限。所有的这些权限都记录在数据库中,这带来了另外一个问题就是需要维护的权限数据量非常庞大,不利于后期扩展。当然,对于一个简单的系统,使用 Acl 还是可以的,没有任何问题。

2.1 核心概念

接下来我们来看看 Acl 中一些核心概念。

Sid

Sid 代表了用户和角色,它有两种:GrantedAuthoritySid 和 PrincipalSid,前者代表角色,后者代表用户。在 Spring Security 中,用户和角色信息都是保存在 Authentication 对象中的,即 Sid 是从 Authentication 对象中提取出来的,提取出来的值是 GrantedAuthoritySid+PrincipalSid,而不是其中某一项,具体的提取方法是 SidRetrievalStrategyImpl#getSids,相关源码如下:

public List<Sid> getSids(Authentication authentication) {
	Collection<? extends GrantedAuthority> authorities = roleHierarchy
			.getReachableGrantedAuthorities(authentication.getAuthorities());
	List<Sid> sids = new ArrayList<>(authorities.size() + 1);
	sids.add(new PrincipalSid(authentication));
	for (GrantedAuthority authority : authorities) {
		sids.add(new GrantedAuthoritySid(authority));
	}
	return sids;
}

这个 Sid 大家可以简单理解为当前用户的权限(这个说法不是很准确,可以近似理解)。

ObjectIdentity

ObjectIdentity 是一个域对象,这是官方的说法,有点拗口。实际上这就是你要操作的对象。

例如我有一个 User 对象,如果直接去记录能够对 User 对象执行哪些操作,这就会导致高耦和。所以我们需要对其解耦,将所有需要操作的对象通过 ObjectIdentity 描述出来,这样就能确保权限系统不和具体的业务绑定。

ObjectIdentity 中有两个关键方法,getType 和 getIdentifier。一般来说,getType 方法返回真实对象类的全路径,例如 org.javaboy.acl.model.User,getIdentifier 方法则返回真实对象的 id,通过这两个方法,就能够锁定一个对象。

Acl

看名字就知道,这算是整个系统的核心调度部分。

一个 Acl 对象会关联一个 ObjectIdentity,一个 Acl 对象还拥有一个 Sid,这个 Sid 表示这个 Acl 是属于谁的?属于谁,谁就可以修改甚至删除这个 Acl 对象。

AccessControlEntry

AccessControlEntry 简写为 ACE,一个 AccessControlEntry 对象代表一条权限记录。每一个 AccessControlEntry 都对应了一个 Acl,一个 Acl 对象对应多个 AccessControlEntry,有了这层对应关系,相当于就知道这个权限操作的是哪个对象。

然后 AccessControlEntry 中还包含一个 Sid 和一个 Permission 对象,表示某个 Sid 具备某种权限。

可以看到,Acl+ACE,就描述出来了某个 Sid 可以具备某个 ObjectIdentity 的某种 Permission。

Permission

这个就是具体的权限对象。似乎是受 Linux 影响,它使用了权限掩码,最多支持 232-1 种权限。

Spring Security 种默认定义了五种

public class BasePermission extends AbstractPermission {
	public static final Permission READ = new BasePermission(1 << 0, 'R'); // 1
	public static final Permission WRITE = new BasePermission(1 << 1, 'W'); // 2
	public static final Permission CREATE = new BasePermission(1 << 2, 'C'); // 4
	public static final Permission DELETE = new BasePermission(1 << 3, 'D'); // 8
	public static final Permission ADMINISTRATION = new BasePermission(1 << 4, 'A'); // 16

	protected BasePermission(int mask) {
		super(mask);
	}

	protected BasePermission(int mask, char code) {
		super(mask, code);
	}
}

 AclService

AclService 接口中主要定义了一些解析 Acl 对象的方法,通过 ObjectIdentity 对象解析出其对应的 Acl。

AclService 主要有两类实现接口:

  • JdbcAclService
  • JdbcMutableAclService

前者主要是针对 Acl 的查询操作,后者支持 Acl 的添加、更新以及删除等操作。我们常用的是 JdbcMutableAclService。

至此,Acl 中一些核心概念就和小伙伴们介绍完了。

2.2 Acl 数据表

上面提到的对象数据,都需要对应的数据表来维护,在 spring-security-acl 依赖中,为这些数据表都提供了脚本。

可以看到,针对不同类型的数据库,都有对应的脚本。

这里主要涉及到四张表,接下来松哥以 MySQL 脚本为例,来分别介绍每张表的作用及其字段的含义。

acl_class

acl_class 是用来保存对象类型的全路径,如下:

这里的 id 自增长,class 中保存的是相应对象的全路径名。

acl_sid

acl_sid 表用来保存 Sid 的。

根据前面的介绍,存在两种类型的 Sid,GrantedAuthoritySid 和 PrincipalSid。所以这里的 principal 字段表示该 Sid 是哪种类型的。

acl_object_identity

acl_object_identity 用来保存需要进行访问控制的对象信息。

  • object_id_class:关联 acl_class.id。
  • object_id_identity:需要控制的对象的 id。
  • parent_object:父对象 ID,关联一条 acl_object_identity 记录。
  • owner_sid:这个 acl 记录拥有者的 sid。
  • entries_inheriting:是否需要继承父对象的权限。

简单来说,这个表中的 object_id_class 和 object_id_identity 字段锁定了你要进行权限控制的对象,具体如何控制呢?则要看 acl_entry 中的关联关系了。

acl_entry

这个表单纯看数据,一堆数字。

松哥来捋一下,大家就懂了。

  • acl_object_identity:关联 acl_object_identity.id。
  • ace_order:权限顺序。
  • acl_object_identity 和 ace_order 的组合要唯一。
  • sid:关联 acl_sid.id。
  • 这条权限记录关联哪个用户/角色。
  • mask:权限掩码。
  • granting:表示当前记录是否生效。
  • audit_success/audit_failure:审计信息。

简单来说,acl_entry 中的一条记录,关联了一个要操作的对象(acl_object_identity 和 ace_order 字段),关联了 Sid(sid 字段),也描述了权限(mask),将权限涉及到的东西都在该字段中整合起来了。

3.小结

好啦,这就本文和小伙伴们科普一下 ACL 的概念,下篇文章松哥通过一个完整的案例来和小伙伴们演示具体用法~

参考资料:

https://blog.gaoyuexiang.cn/2020/07/02/spring-security-acl-conception-and-component

https://www.iteye.com/blog/elim-2269021

到此这篇关于Spring Security 中细化权限粒度的方法的文章就介绍到这了,更多相关Spring Security 细化权限粒度内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题的解决方法

    当前后端分离时,权限问题的处理也和我们传统的处理方式有一点差异.笔者前几天刚好在负责一个项目的权限管理模块,现在权限管理模块已经做完了,我想通过5-6篇文章,来介绍一下项目中遇到的问题以及我的解决方案,希望这个系列能够给小伙伴一些帮助.本系列文章并不是手把手的教程,主要介绍了核心思路并讲解了核心代码,完整的代码小伙伴们可以在GitHub上star并clone下来研究.另外,原本计划把项目跑起来放到网上供小伙伴们查看,但是之前买服务器为了省钱,内存只有512M,两个应用跑不起来(已经有一个V部落开

  • SpringBoot+Spring Security+JWT实现RESTful Api权限控制的方法

    摘要:用spring-boot开发RESTful API非常的方便,在生产环境中,对发布的API增加授权保护是非常必要的.现在我们来看如何利用JWT技术为API增加授权保护,保证只有获得授权的用户才能够访问API. 一:开发一个简单的API 在IDEA开发工具中新建一个maven工程,添加对应的依赖如下: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-b

  • spring security动态配置url权限的2种实现方法

    缘起 标准的RABC, 权限需要支持动态配置,spring security默认是在代码里约定好权限,真实的业务场景通常需要可以支持动态配置角色访问权限,即在运行时去配置url对应的访问角色. 基于spring security,如何实现这个需求呢? 最简单的方法就是自定义一个Filter去完成权限判断,但这脱离了spring security框架,如何基于spring security优雅的实现呢? spring security 授权回顾 spring security 通过FilterCh

  • 话说Spring Security权限管理(源码详解)

    最近项目需要用到Spring Security的权限控制,故花了点时间简单的去看了一下其权限控制相关的源码(版本为4.2). AccessDecisionManager spring security是通过AccessDecisionManager进行授权管理的,先来张官方图镇楼. AccessDecisionManager AccessDecisionManager 接口定义了如下方法: //调用AccessDecisionVoter进行投票(关键方法) void decide(Authent

  • Spring Boot中使用 Spring Security 构建权限系统的示例代码

    Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作. 权限控制是非常常见的功能,在各种后台管理里权限控制更是重中之重.在Spring Boot中使用 Spring Security 构建权限系统是非常轻松和简单的.下面我们就来快速入门 Spring Security .在开始前我们需要一对

  • java中自定义Spring Security权限控制管理示例(实战篇)

    背景描述 项目中需要做细粒的权限控制,细微至url + httpmethod (满足restful,例如: https://.../xxx/users/1, 某些角色只能查看(HTTP GET), 而无权进行增改删(POST, PUT, DELETE)). 表设计 为避嫌,只列出要用到的关键字段,其余敬请自行脑补. 1.admin_user 管理员用户表, 关键字段( id, role_id ). 2.t_role 角色表, 关键字段( id, privilege_id ). 3.t_privi

  • Spring Security 中细化权限粒度的方法

    有小伙伴表示微人事(https://github.com/lenve/vhr)的权限粒度不够细.不过松哥想说的是,技术都是相通的,明白了 vhr 中权限管理的原理,在此基础上就可以去细化权限管理粒度,细化过程和还是用的 vhr 中用的技术,只不过设计层面重新规划而已. 当然今天我想说的并不是这个话题,主要是想和大家聊一聊 Spring Security 中权限管理粒度细化的问题.因为这个问题会涉及到不同的权限管理模型,今天和小伙伴们聊一聊- 1.权限管理模型 要想将细化权限粒度,我们不可避免会涉

  • 详解Spring Security 中的四种权限控制方式

    Spring Security 中对于权限控制默认已经提供了很多了,但是,一个优秀的框架必须具备良好的扩展性,恰好,Spring Security 的扩展性就非常棒,我们既可以使用 Spring Security 提供的方式做授权,也可以自定义授权逻辑.一句话,你想怎么玩都可以! 今天松哥来和大家介绍一下 Spring Security 中四种常见的权限控制方式. 表达式控制 URL 路径权限 表达式控制方法权限 使用过滤注解 动态权限 四种方式,我们分别来看.  1.表达式控制 URL 路径权

  • 详解Spring Security中权限注解的使用

    目录 1. 具体用法 2. SpEL 3. @PreAuthorize 最近有个小伙伴在微信群里问 Spring Security 权限注解的问题: 很多时候事情就是这么巧,松哥最近在做的 tienchin 也是基于注解来处理权限问题的,所以既然大家有这个问题,咱们就一块来聊聊这个话题. 当然一些基础的知识我就不讲了,对于 Spring Security 基本用法尚不熟悉的小伙伴,可在公众号后台回复 ss,有原创的系列教程. 1. 具体用法 先来看看 Spring Security 权限注解的具

  • Spring Security 中如何让上级拥有下级的所有权限(案例分析)

    答案是能! 松哥之前写过类似的文章,但是主要是讲了用法,今天我们来看看原理! 本文基于当前 Spring Security 5.3.4 来分析,为什么要强调最新版呢?因为在在 5.0.11 版中,角色继承配置和现在不一样.旧版的方案我们现在不讨论了,直接来看当前最新版是怎么处理的. 1.角色继承案例 我们先来一个简单的权限案例. 创建一个 Spring Boot 项目,添加 Spring Security 依赖,并创建两个测试用户,如下: @Override protected void con

  • 详解Spring Security如何在权限中使用通配符

    目录 前言 1. SpEL 2. 自定义权限该如何写 3. 权限通配符 4. TienChin 项目怎么做的 前言 小伙伴们知道,在 Shiro 中,默认是支持权限通配符的,例如系统用户有如下一些权限: system:user:add system:user:delete system:user:select system:user:update … 现在给用户授权的时候,我们可以像上面这样,一个权限一个权限的配置,也可以直接用通配符: system:user:* 这个通配符就表示拥有针对用户的

  • 详解Spring Security中获取当前登录用户的详细信息的几种方法

    目录 在Bean中获取用户信息 在Controller中获取用户信息 通过 Interface 获取用户信息 在JSP页面中获取用户信息 在Bean中获取用户信息 Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (!(authentication instanceof AnonymousAuthenticationToken)) { String currentU

  • Spring security用户URL权限FilterSecurityInterceptor使用解析

    这篇文章主要介绍了Spring security用户URL权限FilterSecurityInterceptor使用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 用户通过浏览器发送URL地址,由FilterSecurityInterceptor判断是否具有相应的访问权限. 对于用户请求的方法权限,例如注解@PreAuthorize("hasRole('ADMIN')"),由MethodSecurityInterceptor判断

  • 解决Spring Security中AuthenticationEntryPoint不生效相关问题

    目录 在这里我的代码如下 用不存在的用户名密码登录后会出现以下返回数据 以下是配置信息 以下是实现的验证码登录过滤器 以下是对应的源码 我们首先看一下当前Security的拦截器链 为了保证拦截器链能顺利到达ExceptionTranslationFilter 之前由于项目需要比较详细地学习了Spring Security的相关知识,并打算实现一个较为通用的权限管理模块.由于项目是前后端分离的,所以当认证或授权失败后不应该使用formLogin()的重定向,而是返回一个json形式的对象来提示没

  • Spring Security OAuth2 token权限隔离实例解析

    这篇文章主要介绍了Spring Security OAuth2 token权限隔离实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 由于项目OAuth2采用了多种模式,授权码模式为第三方系统接入,密码模式用于用户登录,Client模式用于服务间调用, 所有不同的模式下的token需要用 @PreAuthorize("hasAuthority('client')") 进行隔离,遇到问题一直验证不通过. 通过调试发现资源服务从授权服

  • spring security中的csrf防御原理(跨域请求伪造)

    什么是csrf? csrf又称跨域请求伪造,攻击方通过伪造用户请求访问受信任站点.CSRF这种攻击方式在2000年已经被国外的安全人员提出,但在国内,直到06年才开始被关注,08年,国内外的多个大型社区和交互网站分别爆出CSRF漏洞,如:NYTimes.com(纽约时报).Metafilter(一个大型的BLOG网站),YouTube和百度HI......而现在,互联网上的许多站点仍对此毫无防备,以至于安全业界称CSRF为"沉睡的巨人". 举个例子,用户通过表单发送请求到银行网站,银行

随机推荐