如何在春季oauth2 OAuth2AccessToken请求上设置代理,或者如何覆盖OAuth2AccessTokenSupport restTemplate变量?

Kar*_*yan 5 proxy spring spring-security spring-boot spring-security-oauth2

我尝试通过以下方式设置网络代理,但任何一种方法均无效

1:设置jvm变量,例如-Dhttp.proxyHost = -Dhttp.proxyPort = .......
2:创建Bean。

@Bean
public RestTemplate restTemplate() {
    final String proxyHost = "######"; // host
    final int proxyPort = ####;  // port
    SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
    factory.setProxy(new Proxy(Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)));
    return new RestTemplate(factory);
}
Run Code Online (Sandbox Code Playgroud)

但是,此配置被OAuth2AccessTokenSupport.restTemplate覆盖。

因此,以下方法始终返回新创建的rest模板对象。

org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport

protected RestOperations getRestTemplate() {
    if (restTemplate == null) {
        synchronized (this) {
            if (restTemplate == null) {
                RestTemplate restTemplate = new RestTemplate();
                restTemplate.setErrorHandler(getResponseErrorHandler());
                restTemplate.setRequestFactory(requestFactory);
                restTemplate.setInterceptors(interceptors);
                this.restTemplate = restTemplate;
            }
        }
    }
    if (messageConverters == null) {
        setMessageConverters(new RestTemplate().getMessageConverters());
    }
    return restTemplate;
}
Run Code Online (Sandbox Code Playgroud)

请帮助我在OAuth客户端应用程序的其余模板上覆盖或设置代理。

小智 7

另一种方法是将自定义 AccessTokenProvider 设置为您的 OAuth2RestTemplate。在下面的代码示例中,绕过了 SSL 验证:

@Configuration
public class ConfigLocal {

    @Value("${https.proxyHost}")
    private String proxyHost;

    @Value("${https.proxyPort}")
    private Integer proxyPort;

    @Value("${https.proxyUser}")
    private String proxyUser;

    @Value("${https.proxyPassword}")
    private String proxyPassword;

    @Bean
    public OAuth2RestTemplate oauth2RestTemplate(ClientCredentialsResourceDetails clientCredentialsResourceDetails)
            throws KeyManagementException, KeyStoreException, NoSuchAlgorithmException {
        OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(clientCredentialsResourceDetails);

        // Instanciate a new http client with proxy configuration, and bypass SSL Certificate verification
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(proxyUser, proxyPassword));

        HttpClientBuilder httpClientBuilder =
                HttpClients.custom()
                        .setProxy(new HttpHost(proxyHost, proxyPort))
                        .setDefaultCredentialsProvider(credentialsProvider)
                        .setSSLHostnameVerifier(new NoopHostnameVerifier())
                            .setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, (x509Certificates, s) -> true)
                                    .build());

        // requestFactory
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClientBuilder.build());
        ClientCredentialsAccessTokenProvider clientCredentialsAccessTokenProvider = new ClientCredentialsAccessTokenProvider();
        clientCredentialsAccessTokenProvider.setRequestFactory(requestFactory);

        // accessTokenProvider
        AccessTokenProvider accessTokenProvider = new AccessTokenProviderChain(Arrays.<AccessTokenProvider> asList(
                new AuthorizationCodeAccessTokenProvider(), new ImplicitAccessTokenProvider(),
                new ResourceOwnerPasswordAccessTokenProvider(), clientCredentialsAccessTokenProvider));

        restTemplate.setAccessTokenProvider(accessTokenProvider);

        return restTemplate;
    }
}
Run Code Online (Sandbox Code Playgroud)


Kar*_*yan 1

这可能不是一个简单的解决方案。但最终设法通过以下代码在 oauth 请求上设置代理。

注册过滤器

@Override
protected void configure(HttpSecurity http) throws Exception {
    // @formatter:off
    http.antMatcher("/**")
    .authorizeRequests().antMatchers("/webjars/**", "/scripts/**", "/styles/**", "/instances/**", "/#/invalid").permitAll()
    .anyRequest().authenticated()
    .and().csrf().csrfTokenRepository(csrfTokenRepository())
    .and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
    .addFilterBefore(oauthFilter(), BasicAuthenticationFilter.class);
    // @formatter:on
    super.configure(http);
}
Run Code Online (Sandbox Code Playgroud)

验证过滤器

@Autowired
OAuth2ClientContext oauth2ClientContext;

@Autowired
OAuth2ProtectedResourceDetails resource;

@Autowired
ResourceServerProperties resourceServer;

@Autowired
RequestHelper requestHelper;

private Filter oauthFilter() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
    OAuth2ClientAuthenticationProcessingFilter oauthFilter = new OAuth2ClientAuthenticationProcessingFilter("/login");
    OAuth2RestTemplate oauthTemplate = new OAuth2RestTemplate(resource, oauth2ClientContext);
    OAuth2AccessTokenSupport authAccessProvider = new AuthorizationCodeAccessTokenProvider();
    // Set request factory for '/oauth/token'
    authAccessProvider.setRequestFactory(requestHelper.getRequestFactory());
    AccessTokenProvider accessTokenProvider = new AccessTokenProviderChain(Arrays.<AccessTokenProvider> asList(
            (AuthorizationCodeAccessTokenProvider)authAccessProvider));
    oauthTemplate.setAccessTokenProvider(accessTokenProvider);
    // Set request factory for '/userinfo'
    oauthTemplate.setRequestFactory(requestHelper.getRequestFactory());
    oauthFilter.setRestTemplate(oauthTemplate);
    UserInfoTokenServices userInfoTokenService = new UserInfoTokenServices(resourceServer.getUserInfoUri(), resource.getClientId());
    userInfoTokenService.setRestTemplate(oauthTemplate);
    oauthFilter.setTokenServices(userInfoTokenService);
    return oauthFilter;
}
Run Code Online (Sandbox Code Playgroud)

请求帮助代码

@Configuration
public class RequestHelper {

  @Value("${proxy.hostname}")
  private String proxyHost;

  @Value("${proxy.port}")
  private int proxyPort;

  @Value("${proxy.username}")
  private String proxyUser;

  @Value("${proxy.password}")
  private String proxyPassword;

  @Value("${useProxy}")
  private boolean useProxyFlag;

  @Value("${skipSslValidation}")
  private Boolean skipSslValidationFlag;

  public HttpComponentsClientHttpRequestFactory getRequestFactory() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {

      HttpClientBuilder httpClientBuilder = HttpClients.custom();

      // Skip SSL validation based on condition
      if (skipSslValidationFlag) {
          TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;

          SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
                  .loadTrustMaterial(null, acceptingTrustStrategy)
                  .build();
          SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);

          httpClientBuilder = httpClientBuilder.setSSLSocketFactory(csf);
      }

      // Set proxy based on condition
      if (useProxyFlag) {
          CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
          credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(proxyUser, proxyPassword));
          httpClientBuilder = httpClientBuilder.setProxy(new HttpHost(proxyHost, proxyPort));
          httpClientBuilder = httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
      }

      CloseableHttpClient httpClient = httpClientBuilder.build();
      HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
      requestFactory.setHttpClient(httpClient);
      return requestFactory;
  }
}
Run Code Online (Sandbox Code Playgroud)