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

Spring Boot Security OAuth2 SSO与API权限配置异常排查

看起来你遇到的问题核心在于@EnableOAuth2Sso会默认对所有未认证的请求触发OAuth2登录跳转,包括你的REST API路径——这显然不符合API的预期行为(API应该返回401/403而不是重定向到登录页)。我们需要把前端SSO和API的Bearer Token认证逻辑分开配置,让它们各自使用适合的认证方式。

下面是具体的解决方案:

1. 重构Security配置类

首先去掉@EnableOAuth2Sso注解,改用Spring Security 5+的oauth2Login()(处理前端SSO)和oauth2ResourceServer()(处理API的Bearer Token校验)来分别配置两个路径的认证规则:

@Configuration
public class ProdWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    private static final String ADMIN_ROLE = "role.global.admin";
    private static final String READ_API_ROLE = "role.base.read.api";

    @Value("${base.rootauthuri}")
    private String rootAuthUri;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            // 配置请求权限规则
            .authorizeRequests()
                // 登录、错误页面允许匿名访问
                .antMatchers("/login**", "/error**").permitAll()
                // 前端页面路径:要求ADMIN_ROLE,未认证则跳OAuth登录
                .antMatchers("/*").hasAuthority(ADMIN_ROLE)
                // API路径:要求ADMIN_ROLE或READ_API_ROLE,未认证返回401,权限不足返回403
                .antMatchers("/api/**").hasAnyAuthority(ADMIN_ROLE, READ_API_ROLE)
                .anyRequest().authenticated()
            .and()
                // 配置前端SSO登录逻辑
                .oauth2Login()
                    .loginPage("/oauth2/authorization/client.base.parameters") // 对应你的clientId
                    .defaultSuccessUrl("/", true) // 登录成功后跳首页
            .and()
                // 配置API的Bearer Token认证(JWT模式,适配你的OAuth2服务器)
                .oauth2ResourceServer()
                    .jwt()
                    .jwtAuthenticationConverter(jwtAuthenticationConverter())
            .and()
                // 配置登出逻辑
                .logout()
                .permitAll()
                .logoutSuccessUrl(rootAuthUri + "/connect/endsession");
    }

    // 自定义JWT转换器:把OAuth2服务器返回的角色映射为Spring Security的权限
    private JwtAuthenticationConverter jwtAuthenticationConverter() {
        JwtGrantedAuthoritiesConverter authoritiesConverter = new JwtGrantedAuthoritiesConverter();
        // 这里要根据你的OAuth2服务器返回的JWT中角色的字段名调整,比如如果角色存在"roles"字段里就用这个
        authoritiesConverter.setAuthoritiesClaimName("roles");
        authoritiesConverter.setAuthorityPrefix(""); // 你的角色没有前缀,所以设为空
        // 如果你的角色是在其他字段,比如"permissions",就改成对应的字段名

        JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
        converter.setJwtGrantedAuthoritiesConverter(authoritiesConverter);
        return converter;
    }
}

2. 调整application.properties配置

确保资源服务器的配置正确,添加JWT issuer的配置(如果你的OAuth2服务器支持JWT):

# 原有配置保留,新增以下内容
security.oauth2.resource.jwt.issuer-uri=${base.rootauthuri}

如果你的OAuth2服务器不用JWT,而是通过userInfo接口返回用户信息,那可以保留原有的security.oauth2.resource.userInfoUri配置,同时把资源服务器的配置改成基于userInfo的认证转换器(不过JWT模式更高效)。

关键改动说明

  • 分离认证逻辑:前端页面用oauth2Login()处理SSO跳转,API用oauth2ResourceServer()处理Bearer Token,两者互不干扰。
  • API行为符合REST规范:当API请求没有Token或Token无效时,返回401 Unauthorized;Token有效但权限不足时返回403 Forbidden,不再跳登录页。
  • 角色映射正确:自定义JwtAuthenticationConverter确保OAuth2服务器返回的角色能被Spring Security正确识别,让hasAnyAuthority规则生效。

测试场景验证

  • 访问前端首页(/):未登录会自动跳转到OAuth2登录页,登录后如果没有ADMIN_ROLE会被拒绝(403),有则正常访问。
  • 访问/api/devices:
    • 不带Bearer Token:返回401
    • 带无效/过期Token:返回401
    • 带有效Token但无ADMIN_ROLE或READ_API_ROLE:返回403
    • 带有效Token且拥有其中一个角色:正常返回数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 08:19:09