使用JWT认证访问/admin接口时持续出现403权限错误
问题:拥有ADMIN角色访问/admin路径仍返回403错误
发送JWT令牌请求http://localhost:9090/admin/update-stock等所有/admin路径时,即便账号拥有ADMIN角色,仍每次返回403错误。相关Spring Security配置代码如下:
import org.springframework.security.core.userdetails.UserDetailsService; @Configuration @EnableWebSecurity @EnableMethodSecurity public class WebSecurityConfig { @Bean public UserDetailsService userDetailsService() { return new UserInfoUserDetailsService(); } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { return http .csrf().disable() .authorizeHttpRequests() .requestMatchers( "/signin", "/signup").permitAll() .and() .authorizeHttpRequests() .requestMatchers("/admin/**").hasRole("ADMIN") .and() .authorizeHttpRequests() .requestMatchers("/user/**").hasRole("USER") .anyRequest().authenticated() .and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authenticationProvider(authenticationProvider()) .addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class) .build(); } }
排查方向与解决方案
1. 角色前缀不匹配
Spring Security的hasRole()方法默认会自动给角色名称添加ROLE_前缀。如果你的JWT令牌中存储的角色是ADMIN而非ROLE_ADMIN,就会导致权限匹配失败。
解决方式二选一:
- 改用
hasAuthority("ADMIN")替代hasRole("ADMIN"),hasAuthority()不会添加前缀,直接匹配令牌中的角色字符串 - 确保JWT令牌中存储的角色带
ROLE_前缀,或者通过配置移除默认前缀:@Bean public GrantedAuthorityDefaults grantedAuthorityDefaults() { return new GrantedAuthorityDefaults(""); // 取消默认的ROLE_前缀 }
2. 权限规则顺序问题
当前配置拆分了多个authorizeHttpRequests()块,可能导致规则优先级混乱。建议合并为一个块,保证更具体的路径规则(如/admin/**)放在通用规则(anyRequest())前面:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { return http .csrf().disable() .authorizeHttpRequests(auth -> auth .requestMatchers("/signin", "/signup").permitAll() .requestMatchers("/admin/**").hasAuthority("ADMIN") .requestMatchers("/user/**").hasAuthority("USER") .anyRequest().authenticated() ) .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.STATELESS) ) .authenticationProvider(authenticationProvider()) .addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter.class) .build(); }
3. JWT过滤器未正确解析角色
检查你的authFilter(JWT验证过滤器)是否正确从令牌中提取角色,并将其转换为GrantedAuthority对象存入Authentication上下文。示例代码如下:
// JWT过滤器中解析角色的核心逻辑 List<String> roles = jwtTokenUtil.extractRolesFromToken(token); List<GrantedAuthority> authorities = roles.stream() .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); // 将角色权限存入认证对象 UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( username, null, authorities); SecurityContextHolder.getContext().setAuthentication(authentication);
内容的提问来源于stack exchange,提问作者ASIF KAIF
相关产品推荐
相关产品推荐

