Spring OAuth2配置带凭证代理访问OAuth2.0服务器问题求助
Spring Boot OAuth2客户端配置带凭证代理的解决方案
核心逻辑
Spring Security OAuth2客户端的所有请求(比如授权码交换Token、刷新Token等)都是通过ClientHttpRequestFactory执行的,只要自定义这个工厂并配置代理及凭证,再替换默认的工厂,就能让OAuth请求走带认证的代理。
具体实现步骤
1. 添加HTTP客户端依赖
Spring Boot默认的SimpleClientHttpRequestFactory对代理认证支持有限,推荐使用Apache HttpClient5来处理带凭证的代理,先在pom.xml中添加依赖:
<dependency> <groupId>org.apache.httpcomponents.client5</groupId> <artifactId>httpclient5</artifactId> </dependency>
2. 自定义带代理的ClientHttpRequestFactory
创建配置类,定义带代理凭证的请求工厂Bean:
import org.apache.hc.client5.http.auth.AuthScope; import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; import org.apache.hc.core5.http.HttpHost; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; @Configuration public class ProxyConfig { @Bean public HttpComponentsClientHttpRequestFactory proxyHttpRequestFactory() { // 替换为你的代理服务器地址和端口 HttpHost proxy = new HttpHost("proxy.yourcompany.com", 8080); // 替换为代理的用户名和密码 BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials( new AuthScope(proxy.getHostName(), proxy.getPort()), new UsernamePasswordCredentials("proxy-user", "proxy-pass".toCharArray()) ); CloseableHttpClient httpClient = HttpClients.custom() .setProxy(proxy) .setDefaultCredentialsProvider(credentialsProvider) .setConnectionManager(new PoolingHttpClientConnectionManager()) .build(); HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient); factory.setConnectTimeout(5000); factory.setReadTimeout(5000); return factory; } }
3. 配置OAuth2客户端使用自定义请求工厂
修改你的Security FilterChain配置,让OAuth2的授权码交换请求使用这个代理工厂:
import org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient; import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient; import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest; // 其他必要的导入 // 在你的Security配置类中 @Autowired private HttpComponentsClientHttpRequestFactory proxyHttpRequestFactory; @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers(PAGE_AUTH_SSO_LOGIN, PAGE_AUTH_ERROR, LOGIN_OAUTH2_CALLBACK_URL, AuthenticationUtils.FAILURE_OAUTH_LOGIN_CALLBACK, SpringConstants.ACTUATOR_HEALTH_URL).permitAll() .anyRequest().authenticated() ) .oauth2Login(oauth2 -> oauth2 .loginPage(PAGE_AUTH_SSO_LOGIN) .successHandler((request, response, authentication) -> response.sendRedirect(SUCCESSFUL_OAUTH_LOGIN_CALLBACK)) .failureHandler((request, response, authentication) -> response.sendRedirect(AuthenticationUtils.FAILURE_OAUTH_LOGIN_CALLBACK)) // 配置授权码流程使用代理请求工厂 .authorizationCodeGrant(codeGrant -> codeGrant .tokenEndpoint(tokenEndpoint -> tokenEndpoint .accessTokenResponseClient(accessTokenResponseClient()) ) ) ) .logout(logout -> logout .logoutUrl(LOGOUT_URL) .logoutSuccessUrl("/oauth2/authorization/logout?redirect_uri=http://localhost:8090/page/auth/ssoLogin.xhtml") .clearAuthentication(true) .invalidateHttpSession(true) .deleteCookies(JSESSIONID) ) .csrf().disable(); return http.build(); } // 定义使用代理工厂的Token响应客户端 private OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient() { DefaultAuthorizationCodeTokenResponseClient tokenResponseClient = new DefaultAuthorizationCodeTokenResponseClient(); tokenResponseClient.setRequestFactory(proxyHttpRequestFactory); return tokenResponseClient; }
4. 额外:WebClient请求也走代理(如果需要)
如果你的应用中用WebClient调用OAuth2服务器的其他接口,也可以配置WebClient使用代理:
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider; import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager; import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository; import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.http.client.HttpComponentsClientHttpConnector; // 在配置类中添加 @Autowired private ClientRegistrationRepository clientRegistrationRepository; @Autowired private OAuth2AuthorizedClientRepository authorizedClientRepository; @Autowired private HttpComponentsClientHttpRequestFactory proxyHttpRequestFactory; @Bean public WebClient oauth2WebClient() { OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() .authorizationCode() .refreshToken() .build(); OAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientRepository); authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Filter = new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager); return WebClient.builder() .clientConnector(new HttpComponentsClientHttpConnector(proxyHttpRequestFactory.getHttpClient())) .apply(oauth2Filter.oauth2Configuration()) .build(); }
注意事项
- 确保代理服务器地址、端口、用户名密码正确,可先通过curl测试代理连通性
- 如果代理使用NTLM认证,需要调整HttpClient的认证配置(替换
BasicCredentialsProvider为对应的NTLM认证提供者) - 以上代码适配Spring Boot 3.0.1、Spring Security 3.0.1版本
内容的提问来源于stack exchange,提问作者glethien
相关产品推荐
相关产品推荐

