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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 00:42:45