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

Spring Security认证成功后所有请求返回403 Forbidden问题

问题修复方案

1. 修正SecurityConfig的授权规则

核心问题在于授权规则配置错误,且角色权限前缀不匹配,先调整安全过滤链配置:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http.csrf().disable()
            .authorizeHttpRequests()
            .requestMatchers(publicEndpoints()).permitAll()
            // 私有端点要求已登录用户访问,替换原permitAll配置
            .requestMatchers(userEndpoints()).authenticated()
            .requestMatchers(adminEndpoints()).hasRole("ADMIN")
            // 其他请求默认要求认证(若有特定路径需拒绝,可单独配置)
            .anyRequest().authenticated()
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authenticationProvider(authProvider)
            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
            .exceptionHandling()
            .accessDeniedHandler((request, response, ex) -> {
                System.out.println("Access Denied: " + ex.getMessage());
                response.sendError(HttpServletResponse.SC_FORBIDDEN);
            });

    return http.build();
}

关键修改说明:

  • 把.requestMatchers(userEndpoints()).permitAll()改为.authenticated(),符合「仅已登录用户可访问私有端点」的需求
  • 替换.anyRequest().denyAll()为.authenticated(),避免误拦截未匹配到规则的合法请求

2. 确保角色权限前缀匹配

Spring Security中hasRole("USER")等价于hasAuthority("ROLE_USER"),如果你的UserDetails实现中给用户添加的权限是USER而非ROLE_USER,会导致权限校验失败返回403。

检查UserDetailsService实现,确保权限带ROLE_前缀:

// 示例:正确的权限设置方式
List<GrantedAuthority> authorities = Collections.singletonList(
    new SimpleGrantedAuthority("ROLE_USER")
);
return new User(user.getUsername(), user.getPassword(), authorities);

若不想使用ROLE_前缀,可改用hasAuthority("USER")替代hasRole("USER")。

3. 验证JWT过滤器逻辑

确认JwtAuthenticationFilter的核心逻辑正常工作:

  • 检查jwtService.extractUsername(jwtToken)是否能正确解析用户名
  • 检查jwtService.isTokenValid(jwtToken, userDetails)是否正确验证token签名、过期时间及用户名匹配
  • 确认SecurityContextHolder.getContext().setAuthentication(authToken)代码被执行,且authToken包含正确的用户权限

4. 确保@PreAuthorize注解生效

若使用方法级权限注解@PreAuthorize("hasRole('USER')"),需确保@EnableMethodSecurity开启prePost支持(默认开启,可显式配置):

@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
    // ... 其他配置
}

同时注解中的权限字符串需与UserDetails中的权限保持一致(带ROLE_前缀)。


原现象原因解释

  • 原配置中.requestMatchers(userEndpoints()).permitAll()仍返回403:大概率是请求路径未匹配到/u/**,或JWT过滤器未正确设置认证信息,导致请求被.anyRequest().denyAll()直接拦截(此场景不会触发accessDeniedHandler,因此无日志)
  • 修改为.hasRole("USER")后出现Access Denied日志:说明路径匹配成功,但用户的Authentication不包含ROLE_USER权限,触发权限校验失败

内容的提问来源于stack exchange,提问作者tgoel-dev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 09:37:46