使用 spring gateway 和 Oauth2 配置 Client Credentials Flow

Posted

技术标签:

【中文标题】使用 spring gateway 和 Oauth2 配置 Client Credentials Flow【英文标题】:Configure Client Credentials Flow with spring gateway and Oauth2 【发布时间】:2020-03-27 02:31:47 【问题描述】:

我的客户端应用程序(我的 Spring 网关)中的客户端凭据流配置存在一些问题。

我的授权服务器功能正常,使用 Postman 进行测试没有任何问题。

但在我的客户端应用程序中,似乎 oauth2 配置被破坏而没有编译错误。

当我在我的服务器资源上调用一个受保护的资源时,我的客户端应用程序似乎试图在其基础而不是授权服务器中调用一个 URL。

查看代码 我的配置文件:

security:
    oauth2:
      client:
        registration:
          apigateway:
            provider: apigateway
            client-id: apigateway
            client-secret: password
            scope: generate_token,read,write
            authorization-grant-type: client_credentials
            redirect-uri: "baseUrl/login/oauth2/code/registrationId"
        provider:
          apigateway:
            token-uri: https://localhost:9001/oauth/token

我的客户依赖:

<dependencies>
        <!-- ************ SPRING DEPENDENCIES ************ -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-client</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
    </dependencies>

我的 WebClient 的配置:

public class WebClientSecurityCustomizer implements WebClientCustomizer 

    private ServerOAuth2AuthorizedClientExchangeFilterFunction securityExchangeFilterFunction;

    public WebClientSecurityCustomizer(
            ServerOAuth2AuthorizedClientExchangeFilterFunction securityExchangeFilterFunction) 
        this.securityExchangeFilterFunction = securityExchangeFilterFunction;
    

    @Override
    public void customize(WebClient.Builder webClientBuilder) 

        SslProvider sslProvider = SslProvider.builder().sslContext(
                SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE)
        )
                .defaultConfiguration(SslProvider.DefaultConfigurationType.NONE).build();

        TcpClient tcpClient = TcpClient.create().secure(sslProvider);
        HttpClient httpClient = HttpClient.from(tcpClient);
        ClientHttpConnector httpConnector = new ReactorClientHttpConnector(httpClient);
        webClientBuilder.clientConnector(httpConnector);

        webClientBuilder.filters((filterFunctions) -> 
            if (!filterFunctions.contains(this.securityExchangeFilterFunction)) 
                filterFunctions.add(0, this.securityExchangeFilterFunction);
            
        );
    


@Configuration
public class WebClientSecurityConfiguration 

    @Bean
    public WebClientSecurityCustomizer webClientSecurityCustomizer(
            ReactiveClientRegistrationRepository clientRegistrations) 

        // Provides support for an unauthenticated user such as an application
        ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
                clientRegistrations, new UnAuthenticatedServerOAuth2AuthorizedClientRepository());

        // Build up a new WebClientCustomizer implementation to inject the oauth filter
        // function into the WebClient.Builder instance
        return new WebClientSecurityCustomizer(oauth);
    

    /**
     * Helper function to include the Spring CLIENT_REGISTRATION_ID_ATTR_NAME in a
     * properties Map
     *
     * @param provider - OAuth2 authorization provider name
     * @return consumer properties Map
     */
    public static Consumer<Map<String, Object>> getExchangeFilterWith(String provider) 
        return ServerOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId(provider);
    

我的资源调用者:

return webClientBuilder.build().get().uri(uri+"accessToken", accessToken)
                .attributes(
                        WebClientSecurityConfiguration.getExchangeFilterWith("apigateway"))
               .retrieve()
               .bodyToMono(String.class)
               .flatMap(response -> 
                   ServerHttpRequest request = exchange.getRequest().mutate()
                           .header(jwtHeader, String.format("%s %s", jwtPrefix, response))
                           .build();

                   return chain.filter(exchange.mutate().request(request).build());
               );
    

最后,客户端应用程序中生成的错误(似乎授权和资源服务没有收到请求):

2019-12-02 13:53:50.543 ERROR 11492 --- [ctor-http-nio-2] a.w.r.e.AbstractErrorWebExceptionHandler : [405f3f3c]  500 Server Error for HTTP GET "/oauth2/authorization/apigateway"

java.lang.IllegalArgumentException: Invalid Authorization Grant Type (client_credentials) for Client Registration with Id: apigateway
    at org.springframework.security.oauth2.client.web.server.DefaultServerOAuth2AuthorizationRequestResolver.authorizationRequest(DefaultServerOAuth2AuthorizationRequestResolver.java:156) ~[spring-security-oauth2-client-5.2.1.RELEASE.jar:5.2.1.RELEASE]

非常感谢您的帮助。

【问题讨论】:

你解决了吗?我也面临同样的问题。 您好,Zia 女士,不,抱歉。在这篇文章之后,我们找到了 Spring Security 团队的一篇博文,解释他们正在放弃授权服务器。所以我们决定换一个具体的解决方案。 【参考方案1】:

将下面提到的类添加到您的 Spring Boot 项目中。然后,它可以正常工作而不会出现上述问题。 您需要为任何自定义安全类扩展“WebSecurityConfigurerAdapter”。

import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter 
    @Override
    public void configure(WebSecurity web) throws Exception 
        web.ignoring()
                .antMatchers("/**");

    


【讨论】:

以上是关于使用 spring gateway 和 Oauth2 配置 Client Credentials Flow的主要内容,如果未能解决你的问题,请参考以下文章

Spring Gateway OAuth - 重定向的完整 URL

Spring Cloud Gateway OAuth2 with Spring Security OAuth2 Authorization Server = loop

调用spring oauth2授权服务器时Spring Cloud Gateway卡住

spring cloud gateway + oauth2 实现网关统一权限认证

spring cloud gateway oauth 整合

Spring Cloud Gateway 基于 OAuth2.0 的身份认证