Spring Security 6.1.3中@PreAuthorize注解失效问题求助
在Spring 3.1.3搭配Spring Security 6.1.3环境下,使用@PreAuthorize注解时出现权限控制失效问题。预期配置:
/rest/api/security/hello:公开访问/rest/api/security/boolean:仅允许ROLE_USER访问/rest/api/security/number:仅允许ROLE_ADMIN访问
当前现象:私有接口可正常跳转至登录页,但两种角色(USER/ADMIN)均能访问两个私有接口,@PreAuthorize校验未生效。调用接口时已确认用户权限正确(USER角色显示[ROLE_USER],ADMIN角色显示[ROLE_ADMIN])。
Controller代码
@RestController @RequestMapping(value = "/rest/api/security") public class BaseController extends HateosController{ @GetMapping("/hello") public final String getHello() { return "Ciao!"; } @GetMapping("/boolean") @PreAuthorize("hasRole('ROLE_USER')") public final boolean getBoolean(Authentication authentication) { System.out.println("User Authorities: " + authentication.getAuthorities()); return true; } @GetMapping("/number") @PreAuthorize("hasAuthority('ROLE_ADMIN')") public final Integer getNumber(Authentication authentication) { System.out.println("User Authorities: " + authentication.getAuthorities()); return 115683; } }
SecurityConfig代码
@Configuration @EnableWebSecurity @EnableMethodSecurity public class SecurityConfig { @Bean public UserDetailsService userDetailsService(PasswordEncoder encoder) { UserDetails admin = User.withUsername("admin").password(encoder.encode("admin")).roles("ADMIN").build(); UserDetails user = User.withUsername("user").password(encoder.encode("user")).roles("USER").build(); return new InMemoryUserDetailsManager(admin, user); } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { return http.csrf().disable() .authorizeHttpRequests() .requestMatchers("/rest/api/security/hello").permitAll().anyRequest().authenticated().and().formLogin() .and().build(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
解决建议
开启prePostEnabled配置:Spring Security 6.x中
@EnableMethodSecurity默认禁用pre-post注解支持,需显式开启,修改注解为:@EnableMethodSecurity(prePostEnabled = true)@PreAuthorize属于pre-post注解范畴,必须开启此配置才能触发校验。修正权限表达式写法:
hasRole方法会自动为角色添加ROLE_前缀,因此/boolean接口的注解应改为:
原写法@PreAuthorize("hasRole('USER')")hasRole('ROLE_USER')会实际校验ROLE_ROLE_USER,与用户权限不匹配。/number接口的hasAuthority('ROLE_ADMIN')写法正确,因为roles("ADMIN")构建用户时会自动添加ROLE_前缀,用户权限为ROLE_ADMIN,与表达式匹配。
修复版本兼容性问题:Spring Security 6.x要求依赖Spring Framework 6.0及以上版本,而当前使用的Spring 3.1.3版本过低,存在严重兼容性问题,这很可能是权限校验失效的根本原因。请升级Spring Framework至6.0+版本,确保与Spring Security 6.1.3版本匹配。
内容的提问来源于stack exchange,提问作者Luca Ferretti
相关产品推荐
相关产品推荐

