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
相关产品推荐
相关产品推荐

