Spring Security 6 系列之五 - 授权管理
之所以想写这一系列,是因为之前工作过程中使用Spring Security,但当时基于spring-boot 2.3.x,其默认的Spring Security是5.3.x。之后新项目升级到了spring-boot 3.3.0,结果一看Spring Security也升级为6.3.0,关键是其风格和内部一些关键Filter大改,导致在配置同样功能时,多费了些手脚,因此花费了些时间研究新版本的底层原理,这里将一些学习经验分享给大家。
注意:由于框架不同版本改造会有些使用的不同,因此本次系列中使用基本框架是 spring-boo-3.3.0(默认引入的Spring Security是6.3.0),JDK版本使用的是19,所有代码都在spring-security-study项目上:https://github.com/forever1986/spring-security-study.git
目录
- 1 Spring Security的授权
- 1.1 两种授权方式
- 1.2 Spring Security授权原理
- 2 权限模型
- 2.1 ACL
- 2.2 RBAC
- 2.3 ABAC
- 3 实践项目经验
在前面我们已经深度了解了Spring Security的认证以及其原理。我们这里将开始了解Spring Security另外一个功能:授权
1 Spring Security的授权
所谓的授权,也可以称为访问控制。无论网络上的资源或者你设计的接口(其实也是一种资源),都需要对其访问进行控制。而之前我们只是简单的使用有登陆即可随意访问,现在我们开始详细控制每个不同资源需要的权限进行控制。
代码参考lesson05子模块
1.1 两种授权方式
基于Ant表达式
在Spring Security的HttpSecurity中,我们可以通过代码的方式实现授权。
http// 所有访问都必须认证.authorizeHttpRequests(auth->auth// 访问manager方法,需要具备manager权限.requestMatchers("/manager").hasAuthority("manager")// 访问operate下所有子方法,需要具备operate权限.requestMatchers("/operate/**").hasAuthority("operate")// 访问info方法,只需要具备info、operate或者manager权限都可以访问.requestMatchers("/info").hasAnyAuthority("info","operate", "manager")// 其它访问都必须认证.anyRequest().authenticated())// 默认配置.formLogin(Customizer.withDefaults());
基于注解和SpEl表达式
在Spring Security的HttpSecurity中,我们可以通过注解的方式实现授权。
注意:使用注解方式,需要在SecurityConfig中加入类加入:@EnableMethodSecurity 注解
@RestController
public class InfoAnnotationController {@GetMapping("/infowithannotation")@PreAuthorize("hasAuthority('info')") // 需要具备info权限才能方法public String info() {return"info";}}
1.2 Spring Security授权原理
我们从上面简单的演示了如何给资源配置权限,其实细心的朋友可以发现Spring Security除了hasAuthority方法外,还有一个hasRole。关于这2个有什么区别,Spring Security最初的设想就是为了实现ACLs和RBAC权限模型,这部分我们下面会细讲,但是从代码实现上,最终都是对字符串的匹配,并没有实质的区别。Spring Security在hasRole中只是会将权限增加**ROLE_**前缀而已。下面来从源码看看Spring Security的授权原理
1)首先,Spring Security授权的过滤器是:AuthorizationFilter,该过滤器的doFilter方法中调用了AuthorizationManager的check方法进行验证(当然像注解的方式就是通过AOP而非该AuthorizationFilter过滤器,但是注解的子类也是实现AuthorizationManager)
2)上面调用的AuthorizationManager接口的check,其实默认调用的是RequestMatcherDelegatingAuthorizationManager代理,而该代理类会根据匹配度,找到对应的AuthorizationManager进行校验
3)我们从代码中了解到AuthorizationManager有丰富的授权继承类,主要是为了实现不同授权方式:
- AuthorityAuthorizationManager:用于基于用户角色或权限进行授权。使用hasRole或hasAuthority来检查用户的角色或权限,适用于需要基于用户角色或权限进行访问控制的场景。
- WebExpressionAuthorizationManager:使用 SpEL(Spring Expression Language)来定义灵活的授权规则。
- PreAuthorizeAuthorizationManager:支持使用 @PreAuthorize 注解对方法调用进行授权控制。
2 权限模型
我们了解完Spring Security的授权方式,我们还需要了解三种不同的权限模型。
2.1 ACL
ACL是一种基于对象和主体的权限控制模型,它通过为每个对象定义一个访问列表来进行权限管理,根据对特定对象的访问权限,来控制主体对该对象的访问。ACL是最细粒度的权限控制方式,它直接将每个对象(如文件、目录或网络资源)的权限分配给具体的用户或者用户组。简单理解:就是有一个用户表,一个权限表,再有一个用户和权限关系表,什么用户拥有什么权限,通过该方式做权限判断。
2.2 RBAC
基于ACL是一个相对直观且简单的权限模型,但是实际应用中,你在给用户分配权限的时候,会有比较大的麻烦,就是拥有类似权限的用户,你需要每个用户都是把权限都加一遍。这时候就会想到,拥有类似权限的用户其实就是具备一样的角色的用户。那么是否可以引入一个角色表,让角色与权限相关联,然后用户与角色相关联,这样你只需要把角色配置给用户即可,不需要每个权限都加入到用户中,因此就诞生了RBAC。
RBAC是一种按角色进行权限管理的模型,它将用户分配给特定角色,然后为每个角色分配权限。这样可以简化权限管理,提高安全性和可维护性。RBAC模型中主要包括以下几个要素:
- 角色(Role):角色是权限管理的核心,它是一组权限的集合,表示了一类用户所拥有的访问权限。角色应该根据组织的职能和权限划分得当,以便有效管理权限和精细控制用户的访问。
- 用户(User):系统中的实际用户,通过将用户分配到不同的角色来获得相应的权限。
- 权限(Permission):权限是指对系统资源进行操作的许可,可以是读取、写入、修改、删除等不同操作。
- 用户-角色关联关系(User-Role Assignment):将用户分配到相应的角色,以确定用户的权限范围。
- 角色-权限关联关系(Role-Permission Assignment):确定不同角色拥有的具体权限。
2.3 ABAC
ABAC是一种基于属性的权限控制模型,它通过定义规则来根据主体和对象的属性来控制访问权限。这种模型可以更灵活地控制访问权限,根据更多的因素来做出访问决策。在ABAC模型中,访问决策是基于用户的属性,如角色、部门、地理位置、所属组织等,以及资源的属性,如文件类型、所属部门等。此外,环境的属性,如时间、地点等,也可以用于决定访问权限。ABAC模型的核心概念包括:
- 属性:ABAC模型以属性为基础来描述用户、资源和环境。属性通常包括标识符、类型和值。例如,一个用户的属性可以是他的部门或职位,而一个资源的属性可能是它所属的项目或类型。
- 策略:ABAC模型中的访问控制策略是根据属性来制定的。策略可以使用逻辑表达式来组合多个属性,以确定访问权限。例如,一个策略可以规定只有部门为“销售部”且角色为“经理”的用户才能访问销售报表。
- 访问控制决策:ABAC模型使用属性来做决策,根据用户的属性、资源的属性和环境的属性来决定用户是否有权访问某个资源。访问决策可以灵活地根据不同的属性组合来调整访问权限。
RBAC其实就是ABAC的一种特例,也就是属性是角色的,但是ABAC的属性可以是其它。
3 实践项目经验
在上面,我们了解了Spring Security的授权方式,同时也了解了三种不同的权限模型。那么在实际业务中,我们如何选择以及是否会使用Spring Security原始的方式进行权限管理呢?
- 第一:三种不同的权限模型,主要是针对不同的业务权限复杂度。如果你的访问资源较少也简单,基于ACL模型就足够。大部分复杂的业务系统都是采用RBAC权限模型。而ABAC则为更大或者说兼容更广泛的权限,比如很多云平台的RAM访问控制运用的就是ABAC模型
- 第二:我们看到Spring Security的权限配置都是写入代码中,而在实际使用过程中,我们往往会有基于系统-菜单-功能的结构性配置,因此往往在实际使用中,比较少会基于Spring Security原始的配置方法,而是会有自己实现一个权限后台。当然如果你们业务模型与Spring Security符合,你可以直接使用。
结语:我们在本章中了解了授权(访问控制)的原理以及一些基本权限模型,这样我们就已经基本了解Spring Security的认证和授权两大重要模块。接下来我们可能会更深入或者说跟贴近实践使用Spring Security的功能,下一章我们从Session会话管理开始。