Spring Security URL权限配置异常:USER角色可访问ADMIN专属接口
问题排查与解决方案
你的问题核心是Spring Security的角色权限限制未生效,已认证的普通用户能访问仅允许ADMIN角色的接口。结合Spring Boot 2.7.5版本,从以下几个方向排查:
1. 角色前缀匹配问题
Spring Security的hasRole()方法默认会自动为角色名称添加ROLE_前缀。例如hasRole('ADMIN')实际检查的是用户是否拥有ROLE_ADMIN权限。如果你的Principal中存储的角色是ADMIN(不带ROLE_前缀),那么这个条件永远无法匹配,导致权限校验失效,任何已认证用户都能访问受限制接口。
解决方式二选一:
- 方式一:在构建用户权限时添加前缀
在JWT过滤器中构造GrantedAuthority时,为角色名称加上ROLE_前缀:List<GrantedAuthority> authorities = Arrays.stream(userRoles.split(",")) .map(role -> new SimpleGrantedAuthority("ROLE_" + role)) .collect(Collectors.toList()); - 方式二:改用
hasAuthority()替代hasRole()hasAuthority()会直接匹配角色名称,无需前缀。修改配置代码:.antMatchers(HttpMethod.DELETE, "/api/user/*").hasAuthority("ADMIN") .antMatchers(HttpMethod.POST, "/api/user").hasAuthority("ADMIN")
2. 优化权限配置写法
原配置中使用.access("hasRole('ADMIN')")的表达式写法,推荐改用更直观的链式调用方法,避免表达式解析可能出现的问题:
修改后的配置片段:
.authorizeRequests() .antMatchers(HttpMethod.DELETE, "/api/user/*").hasRole("ADMIN") .antMatchers(HttpMethod.POST, "/api/user").hasRole("ADMIN") .antMatchers("/auth/login").anonymous() .anyRequest().authenticated()
3. 确认JWT过滤器的权限设置正确
调试时已确认Principal拥有正确角色,需进一步验证过滤器中构造的Authentication对象是否包含正确的权限列表:
确保在JWT过滤器中,将解析出的角色正确转换为GrantedAuthority实例,并设置到UsernamePasswordAuthenticationToken中:
// 解析JWT获取用户角色 String userRoles = jwtUtil.extractRolesFromToken(token); // 构造权限列表 List<GrantedAuthority> authorities = Arrays.stream(userRoles.split(",")) .map(role -> new SimpleGrantedAuthority("ROLE_" + role)) // 对应hasRole的前缀要求 .collect(Collectors.toList()); // 设置认证上下文 UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(username, null, authorities); SecurityContextHolder.getContext().setAuthentication(authToken);
4. 检查是否存在多个SecurityFilterChain
如果项目中存在多个SecurityFilterChain Bean,需确保当前配置的FilterChain优先级更高(Spring Security会优先使用order值更小的FilterChain)。可以为当前Bean添加@Order注解:
@Bean @Order(1) // 数值越小优先级越高 public SecurityFilterChain configure(final HttpSecurity http) throws Exception { // 原有配置 }
内容的提问来源于stack exchange,提问作者Dark Star1
相关产品推荐
相关产品推荐

