1. 引言

Spring Security 作为 Spring Framework 的扩展,能帮我们轻松在应用中实现常见安全实践,包括用户认证、授权、API 保护等。本文聚焦其中的核心组件:AuthorizationManager。我们将深入探讨它在 Spring Security 生态中的定位,以及如何用它来加固应用安全。

2. 什么是 Spring Security AuthorizationManager

AuthorizationManager 是一个接口,用于判断已认证实体是否有权访问受保护资源。Spring Security 通过该接口对基于请求、方法和消息的组件做出最终访问控制决策。

理解 AuthorizationManager 前,需先掌握几个关键概念:

  • 实体:任何能发起系统请求的对象(如用户或远程服务)
  • 认证:验证实体身份的过程(如用户名/密码、令牌等)
  • 授权:验证实体是否有权访问资源的过程
  • 资源:系统中可访问的信息(如 URL 或文档)
  • 权限:常称为角色(Role),表示实体权限的逻辑名称

2.1. 如何使用 AuthorizationManager

AuthorizationManager 接口仅包含两个方法:

AuthorizationDecision check(Supplier<Authentication> authentication, T object);

void verify(Supplier<Authentication> authentication, T object);

两个方法参数相同:

  • authentication:提供发起请求实体的 Authentication 对象
  • object:被请求的安全对象(根据请求类型变化)

但功能不同:

  • check() 返回 AuthorizationDecision(布尔值包装器),表示是否允许访问
  • verify() 无返回值,直接执行授权检查,未授权时抛出 AccessDeniedException

2.2. 旧版 Spring Security 中的实现

⚠️ 踩坑提醒:AuthorizationManager 是 Spring Security 5.0 引入的。此前主要使用 AccessDecisionManager 接口。虽然新版仍保留该接口,但已标记为废弃,应优先使用 AuthorizationManager

3. AuthorizationManager 的实现类

Spring 提供了多种 AuthorizationManager 实现,以下是常用实现:

3.1. AuthenticatedAuthorizationManager

仅根据实体是否已认证返回授权决策,支持三种认证级别:

  • anonymous:未认证
  • remember me:通过记住我认证
  • fully authenticated:完全认证(非记住我)

✅ 这是 Spring Boot Web 应用的默认实现,默认所有接口只要认证通过即可访问。

3.2. AuthoritiesAuthorizationManager

基于多个权限做授权决策,适合复杂场景。例如博客系统:

  • 创建文章:AUTHOREDITOR 角色均可
  • 发布文章:仅 EDITOR 角色可操作

3.3. AuthorityAuthorizationManager

根据实体是否拥有特定角色做决策,适合简单场景。例如:

.requestMatchers("/admin/**").hasRole("ADMIN")

✅ 实际内部委托给 AuthoritiesAuthorizationManager,是调用 hasRole()/hasAuthority() 时的默认实现。

3.4. RequestMatcherDelegatingAuthorizationManager

根据 URL 模式委托给其他实现。例如:

  • 公开 URL → 委托给总是允许的空实现
  • 受保护 URL → 委托给 AuthoritiesAuthorizationManager

这正是 Spring 在 SecurityFilterChain 中添加请求匹配器时的底层机制

3.5. ObservationAuthorizationManager

包装其他实现,**额外记录授权决策的监控指标**。当应用中存在有效的 ObservationRegistry 时,Spring 会自动启用。

3.6. 其他实现类

Spring Security 还提供与注解对应的实现:

  • SecuredAuthorizationManager@Secured
  • PreAuthorizeAuthorizationManager@PreAuthorize
  • PostAuthorizeAuthorizationManager@PostAuthorize

所有安全注解都有对应的 AuthorizationManager 实现

3.7. 组合使用多个 AuthorizationManager

实际开发中常组合使用多个实现。看这个 SecurityFilterChain 示例:

@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests((authorize) -> authorize
        .requestMatchers("/posts/publish/**").hasRole("EDITOR")
        .requestMatchers("/posts/create/**").hasAnyRole("EDITOR", "AUTHOR")
        .anyRequest().permitAll());
    return http.build();
}

这里实际使用了五个 AuthorizationManager:

  1. hasRole("EDITOR") → 创建 AuthorityAuthorizationManager → 委托给新的 AuthoritiesAuthorizationManager
  2. hasAnyRole("EDITOR", "AUTHOR") → 同上机制
  3. permitAll() → 使用 Spring 提供的静态空实现(总是允许访问)

4. 自定义 AuthorizationManager

当内置实现不满足需求时,可自定义实现:

AuthorizationManager<RequestAuthorizationContext> customAuthManager() {
    return new AuthorizationManager<RequestAuthorizationContext>() {
        @Override
        public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext object) {
            // 自定义授权逻辑
        }
    };
}

然后在 SecurityFilterChain 中使用:

SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests((authorize) ->
                    authorize.requestMatchers("/custom/**").access(customAuthManager())
    return http.build();
}

通过 RequestAuthorizationContext 可访问 HTTP 请求,能基于 Cookie、Header 等做决策,甚至委托给第三方服务或数据库实现复杂授权逻辑。

5. 总结

本文深入剖析了 Spring Security 的授权机制:

  • 介绍了 AuthorizationManager 接口及其核心方法
  • 探讨了多种内置实现及其适用场景
  • 演示了如何自定义实现满足特殊需求

所有示例代码可在 GitHub 获取。


原始标题:Spring Security AuthorizationManager