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

Spring Security登录后API访问出现403 Forbidden问题求助

问题排查与解决方案

1. 角色前缀不匹配(最常见触发403的原因)

Spring Security的hasRole()方法会自动为角色名称添加ROLE_前缀。比如你配置hasRole("ADMIN"),实际会校验用户是否拥有ROLE_ADMIN权限;如果数据库中存储的角色值是ADMIN(无前缀),就会出现权限不匹配,直接返回403。

解决方式二选一:

  • 方案一:修改数据库,将角色值改为ROLE_ADMIN、ROLE_USER
  • 方案二:改用hasAuthority()方法(该方法不会自动添加前缀,直接匹配存储的权限值),修改配置中的规则:
    http.authorizeRequests()
            .antMatchers("/secure/**", "/employees/save", "/employees/updateEmployee/{id}", "/employees/deleteEmployee/{id}")
            .hasAuthority("ADMIN")
            .antMatchers("/", "/employees/list", "/employees/getEmployee/{id}",
                    "/employees/getAllEmployeesWithTheseName/{firstname}",
                    "/employees/getEmployeesCustomSortedByName/{direction}")
            .hasAnyAuthority("ADMIN", "USER")
            // 其余配置保持不变
    

2. 安全规则的链式调用错误

你的配置中多次调用.and().authorizeRequests(),这会导致规则被分割,可能出现匹配顺序混乱或规则失效。Spring Security的权限规则是从上到下优先匹配,需用链式调用统一配置所有authorizeRequests规则。

修正后的完整配置示例:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            // 先配置ADMIN专属接口
            .antMatchers("/secure/**", "/employees/save", "/employees/updateEmployee/{id}", "/employees/deleteEmployee/{id}")
            .hasRole("ADMIN")
            // 再配置ADMIN和USER共同可访问的接口
            .antMatchers("/", "/employees/list", "/employees/getEmployee/{id}",
                    "/employees/getAllEmployeesWithTheseName/{firstname}",
                    "/employees/getEmployeesCustomSortedByName/{direction}")
            .hasAnyRole("ADMIN", "USER")
            // 兜底配置:其余所有请求都需要认证
            .anyRequest().authenticated()
            .and()
            .httpBasic()
            .and()
            .formLogin()
            .loginProcessingUrl("/login")
            .defaultSuccessUrl("/swagger-ui.html", true)
            .and()
            .cors()
            .and()
            .csrf().disable();
}

3. UserDetailsService实现问题

检查你的UserDetailsService实现类,确认返回的UserDetails对象中,getAuthorities()方法是否正确返回对应角色权限:

  • 如果用hasRole(),需返回带ROLE_前缀的GrantedAuthority对象,比如new SimpleGrantedAuthority("ROLE_ADMIN")
  • 如果用hasAuthority(),直接返回存储的角色值即可,比如new SimpleGrantedAuthority("ADMIN")

示例实现片段:

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User dbUser = userRepository.findByUsername(username);
    if (dbUser == null) {
        throw new UsernameNotFoundException("用户不存在");
    }
    List<GrantedAuthority> authorities = new ArrayList<>();
    // 若用hasRole(),添加ROLE_前缀;用hasAuthority()则去掉前缀
    authorities.add(new SimpleGrantedAuthority("ROLE_" + dbUser.getRole()));
    return new org.springframework.security.core.userdetails.User(
            dbUser.getUsername(),
            dbUser.getPassword(),
            authorities
    );
}

4. 上下文路径匹配问题

错误日志中的请求路径是/EmployeeManagement/employees/list,说明项目配置了上下文路径EmployeeManagement。Spring Security的antMatchers是相对于上下文路径的,你的配置路径/employees/list本身没问题,但需确认控制器未硬编码上下文路径:

// 正确写法
@RestController
@RequestMapping("/employees")
public class EmployeeController {
    // ...
}

// 错误写法(禁止硬编码上下文路径)
@RestController
@RequestMapping("/EmployeeManagement/employees")
public class EmployeeController {
    // ...
}

内容的提问来源于stack exchange,提问作者Rajat singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 20:05:37