oauth2.0 如何使用JwkSetUri为JWT解码器设置代理,否则请求超时

xqk2d5yq  于 2023-10-15  发布在  其他
关注(0)|答案(1)|浏览(333)

大家好,我有一个设置,将Azure AD访问令牌从前端传递到后端(Springboot),并在后端验证令牌(OAuth2授权服务器),然后提供对API端点的访问。这是我目前的设置。

  • SecurityConfig.java*
package com.devops.Portal.config;

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.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult;
import org.springframework.security.oauth2.jwt.*;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public JwtDecoder jwtDecoder(){
        NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withJwkSetUri("https://login.microsoftonline.com/7521acbc-a68c-41e5-a975-1cf83066dd19/discovery/v2.0/keys").build();
        jwtDecoder.setJwtValidator(new DelegatingOAuth2TokenValidator<Jwt>(
                JwtValidators.createDefaultWithIssuer("https://login.microsoftonline.com/7521acbc-a68c-41e5-a975-1cf83066dd19/discovery/v2.0/keys"),
                new CustomTokenValidator()
        ));
        return jwtDecoder;
    }

    private static class CustomTokenValidator implements OAuth2TokenValidator<Jwt>{

        public OAuth2TokenValidatorResult validate(Jwt jwt){
            if(jwt.getSubject() == null || jwt.getSubject().isEmpty()){
                return OAuth2TokenValidatorResult.failure();
            }else{
                return OAuth2TokenValidatorResult.success();
            }
        }
    }

    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/api/**").authenticated().anyRequest().permitAll().and().oauth2ResourceServer().jwt().decoder(jwtDecoder());
    }
}

但是请求超时了,因为我在一个代理后面。

org.springframework.security.authentication.AuthenticationServiceException: An error occurred while attempting to decode the Jwt: Couldn't retrieve remote JWK set: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://login.microsoftonline.com/asds6d8atsd7ats7dta8sdt/discovery/v2.0/keys": Connection timed out: connect;

因此,如果我尝试了以下步骤来附加代理,

@Bean
    public HttpClient httpClient() {
        HttpClient httpClient = HttpClient.create();
        httpClient = httpClient.proxy(typeSpec -> typeSpec.type(ProxyProvider.Proxy.HTTP).host("http.proxy.example.com").port(8000));
        return httpClient;
    }

    ReactorClientHttpConnector conn = new ReactorClientHttpConnector(httpClient());

    @Bean
    public ReactiveJwtDecoder jwtDecoder (){
        return NimbusReactiveJwtDecoder.withJwkSetUri("https://login.microsoftonline.com/asds6d8atsd7ats7dta8sdt/discovery/v2.0/keys").webClient(WebClient.builder().clientConnector(conn).build()).build();
    }

但我在这一行得到一个错误,

**http.authorizeRequests().antMatchers("/api/**").authenticated().anyRequest().permitAll().and().oauth2ResourceServer().jwt().decoder(jwtDecoder());**

如何在解码器方法中传递reactiveNimbusDecoder。我对OAuth和授权完全是个新手,所以任何指导都很有帮助。

nwsw7zdq

nwsw7zdq1#

您可以提供以下VM参数来设置Java的代理URL和端口:

-Dhttp.proxyHost=<your_proxy_host>
    -Dhttp.proxyPort=<your_proxy_port>
    -Dhttps.proxyHost=<your_proxy_host>
    -Dhttps.proxyPort=<your_proxy_port>

它不允许你使用Reactive解码器的原因是因为Reactive部分意味着一个完全不同的概念(https://projectreactor.io/)。你需要一个标准的NimbusJwtDecoder,但是要定制它使用的HttpClient,你需要在它的构建器上使用它的restOperations方法:

private static void configureOauth2(OAuth2ResourceServerConfigurer<HttpSecurity> resourceServerConfigurer) {

        RestTemplate restTemplate = new RestTemplate();

        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();

        requestFactory.setProxy(new Proxy(Proxy.Type.HTTP, InetSocketAddress.createUnresolved("http.proxy.example.com", 1234));

        restTemplate.setRequestFactory(requestFactory);

        resourceServerConfigurer.jwt(
            jwtConfigurer -> jwtConfigurer.jwtAuthenticationConverter(new OidcAuthenticationConverter())
                .decoder(NimbusJwtDecoder.withJwkSetUri("jwk-set-uri").restOperations(restTemplate).build()));
    }

请记住,这只是一个关于如何创建客户端工厂和代理的快速示例,您可以根据需要进行自定义,但主要的是将您使用代理创建的任何RestTemplate传递给NimbusJwtDecoderBuilder的rest操作方法。
这两种解决方案都可以工作,但如果您只希望解码器使用代理,请使用后一种。

相关问题