AuthorizationManager
是 Spring Security 5.5 引入的一个接口,用于统一处理授权决策。在 Spring Security 中,AuthorizationManager
的不同实现类可用于处理各种授权场景,如基于认证状态、角色、权限等的授权决策。
以下是常见的 AuthorizationManager
实现类及其用途和用法:
1. AuthenticatedAuthorizationManager
- 用途:用于授权所有经过认证的用户。只要用户已经登录,无论角色或权限,均可以访问某些资源。
- 使用场景:例如保护某些资源,使得登录用户都可以访问。
代码示例
import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authz -> authz
.requestMatchers("/authenticated").access(AuthenticatedAuthorizationManager.authenticated()) // 只要登录就可以访问
.anyRequest().permitAll()
)
.formLogin(); // 启用表单登录
return http.build();
}
}
在这里,AuthenticatedAuthorizationManager.authenticated()
表示只要用户已经通过认证,就可以访问 /authenticated
路径。
2. AuthorityAuthorizationManager
- 用途:用于基于用户角色或权限进行授权。可以使用
hasRole
或hasAuthority
来检查用户的角色或权限。 - 使用场景:适用于需要基于用户角色或权限进行访问控制的场景,例如管理员角色才能访问某个路径。
代码示例
import org.springframework.security.authorization.AuthorityAuthorizationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authz -> authz
.requestMatchers("/admin").access(AuthorityAuthorizationManager.hasRole("ADMIN")) // 需要 ADMIN 角色
.requestMatchers("/user").access(AuthorityAuthorizationManager.hasAuthority("ROLE_USER")) // 需要 USER 权限
.anyRequest().permitAll()
)
.formLogin();
return http.build();
}
}
这里使用 AuthorityAuthorizationManager
来基于角色(hasRole
)和权限(hasAuthority
)进行访问控制。
3. WebExpressionAuthorizationManager
- 用途:基于 Spring Security 表达式进行授权控制。使用 SpEL(Spring Expression Language)来定义灵活的授权规则。
- 使用场景:适合需要更灵活或复杂的授权规则,例如基于请求的某些属性或者用户的动态状态。
代码示例
import org.springframework.security.authorization.method.SpringMethodAuthorizationExpressionHandler;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authz -> authz
.requestMatchers("/admin").access(new WebExpressionAuthorizationManager("hasRole('ADMIN')")) // 使用表达式
.requestMatchers("/profile").access(new WebExpressionAuthorizationManager("isAuthenticated() and principal.username == #username"))
.anyRequest().permitAll()
)
.formLogin();
return http.build();
}
}
在这个例子中,WebExpressionAuthorizationManager
通过表达式 hasRole('ADMIN')
来检查是否具有管理员角色,isAuthenticated()
用于检查用户是否已登录,并且 principal.username == #username
用于检查用户是否为当前认证的用户。
4. DelegatingAuthorizationManager
- 用途:这是一个复合
AuthorizationManager
,可以将多个AuthorizationManager
组合在一起,并按顺序执行它们。它会将授权决策委托给不同的AuthorizationManager
,并根据它们的决策来做最终的授权判断。 - 使用场景:当你需要组合多个授权规则时,比如根据不同的条件决定授权结果。
代码示例
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.authorization.DelegatingAuthorizationManager;
import org.springframework.security.authorization.AuthorityAuthorizationManager;
import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
AuthorizationManager<?> compositeAuthManager = DelegatingAuthorizationManager.builder()
.add(AuthenticatedAuthorizationManager.authenticated()) // 首先检查用户是否登录
.add(AuthorityAuthorizationManager.hasRole("ADMIN")) // 然后检查是否有 ADMIN 角色
.build();
http
.authorizeHttpRequests(authz -> authz
.requestMatchers("/admin").access(compositeAuthManager) // 使用组合的 AuthorizationManager
.anyRequest().permitAll()
)
.formLogin();
return http.build();
}
}
在这个例子中,DelegatingAuthorizationManager
组合了两个授权管理器:首先检查用户是否认证通过,然后检查用户是否具备 ADMIN
角色。只有这两个条件都满足时,才允许访问 /admin
。
5. PreAuthorizeAuthorizationManager
- 用途:用于方法级别的授权,支持使用
@PreAuthorize
注解对方法调用进行授权控制。 - 使用场景:适合方法级别的安全控制,通过 Spring Security 的表达式来控制方法调用的权限。
代码示例
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
@Service
public class AdminService {
@PreAuthorize("hasRole('ADMIN')") // 在方法调用前检查权限
public void performAdminTask() {
// 执行管理员任务
}
}
在这个例子中,@PreAuthorize("hasRole('ADMIN')")
会在调用 performAdminTask
方法之前检查用户是否具备 ADMIN
角色。如果用户不具备该角色,将会拒绝方法调用。
总结
AuthenticatedAuthorizationManager
:检查用户是否已经认证(登录),适用于只要登录就可以访问的场景。AuthorityAuthorizationManager
:基于用户角色或权限进行授权,适用于角色或权限控制的场景。WebExpressionAuthorizationManager
:使用 SpEL 表达式定义灵活的授权规则,适合复杂的授权逻辑。DelegatingAuthorizationManager
:复合授权管理器,可以组合多个AuthorizationManager
,适用于复杂的授权逻辑组合。PreAuthorizeAuthorizationManager
:用于方法级别的授权,配合@PreAuthorize
注解,适用于控制方法调用的权限。
根据具体的安全需求,可以选择或组合使用这些 AuthorizationManager
实现类。