升级至Spring Boot 3.0.6后@RolesAllowed验证失败问题
Spring Boot 3.0.6升级后@RolesAllowed配合空角色前缀出现400错误的解决办法
问题背景
将Spring Boot从3.0.2升级到3.0.6修复CVE-2023-20873漏洞后,原本正常的方法级安全验证触发400错误。使用@RolesAllowed注解的接口返回错误信息:
{ "timestamp" : "2023-05-08 04:52:22", "status" : "BAD_REQUEST", "message" : "thunder_admin_app3536576 should not start with since is automatically prepended when using hasAnyRole. Consider using hasAnyAuthority instead." }
此前为满足安全部门要求,配置了空角色前缀:
@Bean GrantedAuthorityDefaults grantedAuthorityDefaults() { return new GrantedAuthorityDefaults(""); }
问题原因
Spring Security 3.0.6版本增强了权限表达式的校验逻辑:@RolesAllowed底层依赖hasRole/hasAnyRole表达式,这类表达式会自动为权限添加配置的角色前缀(此处为空字符串)。新版本校验逻辑禁止权限字符串以配置的前缀开头(空前缀场景下,等价于禁止hasRole直接匹配原始权限),因此触发错误提示。
解决方案
方案1:改用@PreAuthorize配合hasAuthority
hasAuthority表达式不会自动添加角色前缀,直接匹配权限字符串,完全适配空前缀的配置需求。修改代码如下:
@GetMapping(value = "ping",produces = MediaType.TEXT_PLAIN_VALUE) @PreAuthorize("hasAuthority('" + Constants.PUBLIC_CLOUD_ADMIN_ROLE + "')") public ResponseEntity<String> ping(@AuthenticationPrincipal Jwt principal) { return ResponseEntity.ok("We made it!"); }
方案2:调整角色前缀配置(仅安全部门允许时使用)
若安全部门同意使用非空角色前缀,可修改GrantedAuthorityDefaults为非空值,同时确保JWT中的权限字符串带有该前缀。示例:
@Bean GrantedAuthorityDefaults grantedAuthorityDefaults() { return new GrantedAuthorityDefaults("ROLE_"); }
此时JWT中的权限需为ROLE_thunder_admin_app3536576,@RolesAllowed(Constants.PUBLIC_CLOUD_ADMIN_ROLE)中的Constants.PUBLIC_CLOUD_ADMIN_ROLE对应thunder_admin_app3536576即可。
方案3:自定义MethodSecurityExpressionHandler(复杂,不推荐)
通过自定义表达式处理器绕过校验逻辑,但需深入Spring Security表达式解析机制,维护成本较高,仅在上述方案无法实施时考虑。
内容的提问来源于stack exchange,提问作者Howell Evans
相关产品推荐
相关产品推荐

