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

Spring Security 403 Forbidden异常排查:Spring Boot REST API权限问题

解决Spring Security REST API 403 Forbidden问题

我仔细看了你的代码和调试信息,很快找到了导致403错误的核心原因,咱们一步步来解决:

1. 核心问题:权限字符串生成错误

在CustomUserDetails的getAuthorities()方法里,你直接把Role对象和"ROLE_"拼接了,而不是获取Role实体中存储角色名称的role字段值:

// 错误写法
return user.getRoles().stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role)).collect(Collectors.toSet());

这样生成的权限字符串会是类似ROLE_Role(id=1, role=ADMIN)的格式,而Spring Security期望的是ROLE_ADMIN这种标准格式,自然无法匹配你配置的ADMIN角色,导致返回403。

修正后的代码

修改getAuthorities()方法,明确获取Role对象的role字段:

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    return user.getRoles().stream()
        .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getRole()))
        .collect(Collectors.toSet());
}

2. 补充:给Role类添加getter方法

你的Role实体类中定义了private String role;字段,但没有提供对应的getRole()方法,上面的修正代码会编译报错。需要给Role类添加getter(建议同时加setter):

@Table(name = "Roles")
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String role;

    // 添加以下getter和setter
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }
}

3. 可选优化:简化Security配置

你的SecurityConfiguration里重复调用了authorizeRequests(),可以合并成更简洁的写法,功能完全一致:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
        .httpBasic()
        .and()
        .authorizeRequests()
            .antMatchers("/rest/**").permitAll()
            .antMatchers("/secure/**").hasAnyRole("ADMIN")
            .anyRequest().authenticated()
        .and()
        .formLogin()
            .permitAll();
}

验证逻辑

修正后,用户登录时getAuthorities()会生成ROLE_ADMIN权限字符串,无论是你配置的antMatchers("/secure/**").hasAnyRole("ADMIN")还是Controller上的@PreAuthorize("hasAnyRole('ADMIN')"),都会正确匹配(因为hasAnyRole会自动给参数加上ROLE_前缀,实际检查的就是ROLE_ADMIN),这样就能正常访问需要ADMIN角色的接口了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 00:22:36