Spring Boot中如何用类/方法级安全注解替代anyRequest().denyAll()
解决方案
1. 启用方法级安全注解支持
在Spring Security配置类上添加@EnableMethodSecurity注解,开启所需注解支持并设置默认拒绝所有未注解方法:
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity import org.springframework.context.annotation.Configuration @EnableMethodSecurity( prePostEnabled = true, // 启用@PreAuthorize/@PostAuthorize securedEnabled = true, // 启用@Secured jsr250Enabled = true, // 启用@RolesAllowed/@PermitAll defaultAuthorization = "denyAll()" // 全局默认:拒绝所有无注解方法 ) @Configuration class SecurityConfig { // 后续过滤器链配置 }
defaultAuthorization = "denyAll()"是Spring Security 6.1+的新增属性,可直接设置全局默认授权规则。若使用更早版本,可通过自定义MethodSecurityExpressionHandler实现相同效果。
2. 调整SecurityFilterChain配置
修改原有过滤器链逻辑,移除denyAll(),让非公共路径请求通过过滤器链后交由方法级安全注解处理:
import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.web.SecurityFilterChain import org.springframework.http.HttpMethod import org.springframework.context.annotation.Bean @Bean fun securityFilterChain(http: HttpSecurity): SecurityFilterChain = http .csrf { it.disable() } .authorizeHttpRequests { auth -> auth // 开放公共认证路径 .requestMatchers(HttpMethod.POST, "/auth/register", "/auth/login") .permitAll() // 所有其他请求放行至控制器,由方法级安全控制访问 .anyRequest() .permitAll() } // 其他配置(如认证管理器、JWT过滤器等)... .build()
3. 验证注解逻辑(符合需求示例)
示例1:方法级细粒度控制
无注解方法触发默认denyAll(),带注解方法按规则生效:
@RestController class TodoController(private val todoService: TodoService) { @RolesAllowed(Role.ADMIN_VALUE) @GetMapping("/admin/todos") fun method0() = todoService.getAdminTodos() @RolesAllowed(Role.ADMIN_VALUE, Role.USER_VALUE) @GetMapping("/todos") fun method1() = todoService.getUserTodos() @PreAuthorize("isAuthenticated()") @GetMapping("/todos/my") fun method2() = todoService.getMyTodos() @PermitAll @GetMapping("/todos/public") fun method3() = todoService.getPublicTodos() // 无注解,默认拒绝访问 @GetMapping("/todos/secret") fun method4() = todoService.getSecretTodos() }
示例2:控制器类级注解继承
类级注解会应用到所有未单独注解的方法:
// 所有方法允许公共访问 @PermitAll @RestController class PublicTodoController // 所有方法仅允许admin访问 @RolesAllowed(Role.ADMIN_VALUE) @RestController class AdminTodoController // 所有方法仅允许已认证用户访问 @PreAuthorize("isAuthenticated()") @RestController class AuthenticatedTodoController // 无类/方法注解,默认拒绝所有访问 @RestController class RestrictedTodoController
示例3:方法注解覆盖类注解
方法级注解优先级高于类级注解,直接覆盖类规则:
@PreAuthorize("isAuthenticated()") @RestController class TodoController { // 覆盖类注解:允许公共访问 @PermitAll @GetMapping("/todos/public") fun foo() = todoService.getPublicTodos() // 继承类注解:需已认证 @GetMapping("/todos/my") fun bar() = todoService.getMyTodos() // 覆盖类注解:仅admin可访问 @Secured(Role.ADMIN_VALUE) @GetMapping("/admin/todos") fun baz() = todoService.getAdminTodos() }
关键说明
- 过滤器链仅负责放行公共路径,其余请求全部交由方法级安全处理,避免
denyAll()打断注解解析流程。 defaultAuthorization = "denyAll()"确保无注解方法默认拒绝访问,符合"默认禁用所有资源"的核心需求。- 注解优先级遵循:方法注解 > 类注解 > 全局默认规则。
内容的提问来源于stack exchange,提问作者aslary
相关产品推荐
相关产品推荐

