spring security文档阅读

This commit is contained in:
asahi
2024-03-21 19:57:14 +08:00
parent ace697e380
commit 82a6acfe5e

View File

@@ -42,6 +42,15 @@
- [匿名认证配置](#匿名认证配置) - [匿名认证配置](#匿名认证配置)
- [处理logout](#处理logout) - [处理logout](#处理logout)
- [自定义登出url](#自定义登出url) - [自定义登出url](#自定义登出url)
- [Authorization](#authorization)
- [结构](#结构)
- [Invocation Handling](#invocation-handling)
- [基于委托的AuthorizationManager实现](#基于委托的authorizationmanager实现)
- [AuthorityAuthorizationManager](#authorityauthorizationmanager)
- [AuthenticatedAuthorizationManager](#authenticatedauthorizationmanager)
- [AuthorizationManagers](#authorizationmanagers)
- [自定义AuthorizationManager](#自定义authorizationmanager)
- [ROLE继承](#role继承)
# Spring Security # Spring Security
@@ -807,6 +816,107 @@ http
> >
> logoutUrl则是触发logout操作的url。 > logoutUrl则是触发logout操作的url。
## Authorization
### 结构
通过`AuthenticationManager``GrantedAuthority`对象集合被插入到`Authentication`对象中该集合代表被授予给当前主体的权限。插入到Authentication中的`GrantedAuthority`集合将会后续被`AccessDecisionManager`用于判断当前主体是否拥有访问权限。
`GrantedAuthority`接口中只有一个方法:
```java
String getAuthority();
```
该方法只会被`AuthorizationManager`使用通过该方法可以获取代表该权限的String。如果`GrantedAuthority`无法通过一个String精确的描述那么该GrantedAuthority将被视为`复杂的`并且该GrantedAuthority的`getAuthority`方法必须返回null。
如下展示了一个复杂权限的示例:
一个`GrantedAuthority`中存储了多个客户的权限信息每个客户可以进行的操作和可以访问资源的权限都不相同。对于多个客户的权限信息很难勇单个String来表示故而`复杂权限`的实现里,`getAuthority`方法必须返回为null。
如果GrantedAuthority实现的getAuthority方法返回为null这将提示AuthorizationManager需要支持该特定`GrantedAuthority`实现类的解析从而才能读取authority实现中的内容。
Spring Security中包含一个`GrantedAuthority`的实现:`SimpleGrantedAuthority`。该实现能够让任何字符串转化为对应的GrantedAuthority。并且在Spring Security中所有的AuthenticationProvider都使用SimpleGrantedAuthority来注入权限到Authentication对象中。
默认情况下,基于角色的权限管理都以`ROLE_`作为代表权限字符串的开头故而如果当前存在Authorization Rule要求security context中拥有`USER`权限那么Spring Security中是否包含`getAuthority`返回为`ROLE_USER`的GrantedAuthority对象。
如果想要自定义基于角色的权限管理的前缀,可以通过`GrantedAuthorityDefaults`来进行自定义。通过注册`GrantedAuthorityDefaults`类型的bean对象可以进行自定义
```java
@Bean
static GrantedAuthorityDefaults grantedAuthorityDefaults() {
return new GrantedAuthorityDefaults("MYPREFIX_");
}
```
#### Invocation Handling
Spring Security通过拦截器保证了对受保护资源的访问对于method invocation和web request都能进行拦截。AuthorizationManager既会在调用发生前判断当前是否存在调权限也会在调用后判断是否调用结果允许被返回。
AuthorizationManager对AccessDecisionManager和AccessDecisionVoter两者都进行了取代。
AuthorizationManager被spring security的基于基于method组件、基于request组件、基于message组件调用并且AuthorizationManager负责做最后的权限控制决定。AuthorizationManager包含有如下两个方法
```java
AuthorizationDecision check(Supplier<Authentication> authentication, Object secureObject);
default AuthorizationDecision verify(Supplier<Authentication> authentication, Object secureObject)
throws AccessDeniedException {
// ...
}
```
在调用`AuthorizationManager#check`方法时会向其中传入为做出访问决定所需的所有相关信息。特别是传递了secure object这令实际secure object调用中所有的参数都能够在check方法中被观测到。
例如假定该secure object是`MethodInvocation`通过MethodInvocation可以方便的访问调用方法和调用参数并且在check方法中实现一系列逻辑判断当前主体是否拥有权限执行操作。
check方法会返回AuthorizationDecision类型的返回值如果允许当前访问应该返回一个positive AuthorizationDecision如果拒绝当前访问应该返回一个negative AuthorizationDecision如果AuthorizationManager放弃做决定则应该返回null。
`AuthorizationManager#verify`方法会调用check方法若check方法返回negative AuthorizationDecision则verify方法会抛出AccessDeniedException。
#### 基于委托的AuthorizationManager实现
Spring Security设计了一个委托AuthorizationManager其可以和开发者自己实现的复数个AuthorizationManager协作。
`RequestMatcherDelegatingAuthorizationManager`将会为当前请求匹配最适合的AuthorizationManager并将任务委托给匹配到的AuthorizationManager。对于基于方法的权限认证可以使用`AuthorizationManagerBeforeMethodInterceptor``AuthorizationManagerAfterMethodInterceptor`
通过上述的委托机制可以将多个AuthenticationManager组合起来并通过轮询来做Authorization decision。
##### AuthorityAuthorizationManager
`AuthorityAuthorizationManager`是spring security提供的最通用的`AuthorizationManager`
AuthorityAuthorizationManager构造方法接收一系列的权限字符串并且在对Authentication进行校验时会校验构造函数中接收的权限字符串集合其中是否有一个权限字符串在`authentication.getAuthorities`中存在,如果任一权限字符串存在,那么权限校验通过,否则权限校验失败。
##### AuthenticatedAuthorizationManager
AuthenticatedAuthorizationManager可以用于区分anonymous、fully-authenticated、remember-me请求。这可以用于如下场景通过remember-me登录的用户只能够执行有限的操作但是通过full-authenticated登录的用户可以执行所有的操作。
##### AuthorizationManagers
`AuthorizationManagers`类中包含静态工厂方法来将多个单独的AuthorizationManager整合在一起构成更加复杂的表达式。
##### 自定义AuthorizationManager
可以通过实现AuthorizationManager接口来实现任何逻辑的实现类。
#### ROLE继承
通过角色继承,可以配置某些角色包含其他角色,可执行其他角色能做的所有操作。
`RoleHierarchyVoter`作为`RoleVoter`的拓展版本,可以配置`RoleHierarchy`
```java
@Bean
static RoleHierarchy roleHierarchy() {
RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
hierarchy.setHierarchy("ROLE_ADMIN > ROLE_STAFF\n" +
"ROLE_STAFF > ROLE_USER\n" +
"ROLE_USER > ROLE_GUEST");
return hierarchy;
}
// and, if using method security also add
@Bean
static MethodSecurityExpressionHandler methodSecurityExpressionHandler(RoleHierarchy roleHierarchy) {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setRoleHierarchy(roleHierarchy);
return expressionHandler;
}
```
在上述示例中,具有`ADMIN => STAFF => USER => GUEST`的继承关系。一个拥有`ROLE_ADMIN`角色的用户将自动拥有其他角色的权限,其中`>`符号代表包含关系。