Spring Boot应用中使用不同OAuth2 Client保护指定端点
实现多OAuth2客户端的路径级认证方案
核心思路
不需要自定义请求拦截组件,Spring Security原生支持多OAuth2客户端配置,通过多个SecurityFilterChain分别处理不同路径的认证逻辑,同时结合自定义用户服务为特定客户端登录的用户添加权限,就能实现你的需求。
步骤1:配置双OAuth2客户端注册
在application.yml(或properties)中同时配置客户端A和B的信息,确保注册ID分别为A和B:
spring: security: oauth2: client: registration: A: client-id: your-client-a-id client-secret: your-client-a-secret scope: openid,profile,email authorization-grant-type: authorization_code redirect-uri: "{baseUrl}/login/oauth2/code/A" client-name: Client A B: client-id: your-client-b-id client-secret: your-client-b-secret scope: openid,profile,trv-access authorization-grant-type: authorization_code redirect-uri: "{baseUrl}/login/oauth2/code/B" client-name: Client B provider: # 若A和B使用不同的授权服务器,需分别配置provider信息,否则可共用或省略 A: authorization-uri: https://auth-a.com/oauth2/authorize token-uri: https://auth-a.com/oauth2/token user-info-uri: https://auth-a.com/oauth2/userinfo user-name-attribute: sub B: authorization-uri: https://auth-b.com/oauth2/authorize token-uri: https://auth-b.com/oauth2/token user-info-uri: https://auth-b.com/oauth2/userinfo user-name-attribute: sub
步骤2:配置多SecurityFilterChain
创建两个SecurityFilterChain Bean,分别处理普通路径和/trv/**路径的认证规则,注意设置优先级确保/trv/**的链先匹配:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @Configuration @EnableWebSecurity public class SecurityConfig { // 处理/trv/**路径的FilterChain,优先级更高 @Bean public SecurityFilterChain trvSecurityFilterChain(HttpSecurity http) throws Exception { http .securityMatcher(new AntPathRequestMatcher("/trv/**")) .authorizeHttpRequests(auth -> auth .anyRequest().hasRole("TRV_USER") ) .oauth2Login(oauth2 -> oauth2 .clientRegistrationId("B") // 指定使用客户端B的认证流程 .userInfoEndpoint(userInfo -> userInfo .userService(trvOAuth2UserService()) // 自定义用户服务添加权限 ) ); return http.build(); } // 处理其他路径的默认FilterChain @Bean public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers("/").permitAll() // 欢迎页允许匿名访问 .anyRequest().authenticated() ) .oauth2Login(oauth2 -> oauth2 .clientRegistrationId("A") // 默认使用客户端A的认证流程 ); return http.build(); } }
步骤3:自定义OAuth2UserService添加权限
当用户通过客户端B登录成功后,自动为其添加ROLE_TRV_USER权限,确保能访问/trv/**端点:
import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.user.DefaultOAuth2User; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Service; import java.util.Collections; import java.util.Map; @Service public class TrvOAuth2UserService extends DefaultOAuth2UserService { @Override public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { OAuth2User oAuth2User = super.loadUser(userRequest); Map<String, Object> attributes = oAuth2User.getAttributes(); // 添加ROLE_TRV_USER权限 return new DefaultOAuth2User( Collections.singleton(new SimpleGrantedAuthority("ROLE_TRV_USER")), attributes, "sub" // 对应授权服务器返回的用户唯一标识字段,需与provider配置一致 ); } }
关键说明
- 多FilterChain机制:通过
securityMatcher指定每个链负责的路径,优先级高的链会先匹配请求,确保/trv/**的请求走客户端B的认证流程。 - 客户端指定:在
oauth2Login()中通过clientRegistrationId()明确指定使用的客户端,触发对应的授权码流程。 - 权限控制:通过自定义
OAuth2UserService为客户端B的登录用户添加专属角色,结合hasRole()实现端点的权限保护。
当未认证用户访问/trv/**时,会自动重定向到客户端B的授权页面;若用户已通过客户端A登录但无ROLE_TRV_USER权限,也会触发客户端B的认证流程,认证成功后权限会被加入SecurityContext。
内容的提问来源于stack exchange,提问作者Claff
相关产品推荐
相关产品推荐

