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

