You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 20:39:19