Spring Boot 3.1.1集成JWT后注册接口返回403 Forbidden问题排查
针对你遇到的获取JWT令牌后调用需权限接口返回403的问题,以下是常见的配置遗漏点及排查方案:
1. 角色前缀不匹配
Spring Security默认会给hasRole()注解的角色名称自动添加ROLE_前缀。如果你的数据库中存储的角色是ADMIN,但注解用了@PreAuthorize("hasRole('ADMIN')"),实际系统会校验ROLE_ADMIN权限,导致匹配失败。
解决方法:
- 方案一:将注解改为
@PreAuthorize("hasAuthority('ADMIN')")(hasAuthority()直接匹配权限字符串,不添加前缀) - 方案二:在解析JWT时给角色添加
ROLE_前缀,比如:
List<GrantedAuthority> authorities = user.getRoles().stream() .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getName())) .collect(Collectors.toList());
- 方案三:配置Spring Security移除默认前缀:
@Bean public GrantedAuthorityDefaults grantedAuthorityDefaults() { return new GrantedAuthorityDefaults(""); // 清空默认前缀 }
2. JWT过滤器未正确注入权限
如果在JWT认证过滤器中,解析用户权限后没有将其正确注入到Authentication对象中,SecurityContext中的用户会没有权限信息,导致权限校验失败。
检查点:
确保在解析JWT后,将用户角色转化为GrantedAuthority实例并传入UsernamePasswordAuthenticationToken:
// 解析JWT获取用户角色列表 List<String> roles = jwtUtil.extractRoles(token); // 转化为GrantedAuthority集合 List<GrantedAuthority> authorities = roles.stream() .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); // 构建认证对象并设置到SecurityContext UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken( userDetails, null, authorities); SecurityContextHolder.getContext().setAuthentication(authToken);
3. SecurityFilterChain配置顺序或路径错误
Spring Security的拦截规则是按配置顺序匹配的,若权限规则配置在anyRequest().authenticated()之后,会导致权限规则不生效;另外路径匹配错误也会导致权限校验逻辑未触发。
正确配置示例:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) .authorizeHttpRequests(auth -> auth .requestMatchers("/api/auth/login", "/api/auth/register").permitAll() // 放行无需认证的接口 .requestMatchers("/api/auth/admin-register").hasAnyRole("ADMIN", "CASHIER") // 需权限的接口 .anyRequest().authenticated() ) .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); return http.build(); }
注意:Spring Security 6+推荐使用requestMatchers替代旧的antMatchers,确保路径与接口的@RequestMapping完全匹配。
4. 未启用方法级安全
如果使用方法上的@PreAuthorize或@PostAuthorize注解,需要在Security配置类上添加@EnableMethodSecurity注解,否则方法级权限校验不会生效。
示例:
@Configuration @EnableMethodSecurity // 启用方法级安全校验 public class SecurityConfig { // ... 其他配置 }
5. JWT令牌权限字段解析错误
使用JWT解析工具查看令牌中的Claims,确认权限字段(如roles、authorities)的名称和内容是否与代码中解析逻辑一致。比如代码中从roles字段取权限,但令牌中存的是authorities,就会导致无法获取到权限信息。
内容的提问来源于stack exchange,提问作者Leonardo Manzini

