使用OAuth2资源所有者密码授权类型在Spring云网关中创建路由

使用OAuth2资源所有者密码授权类型在Spring云网关中创建路由,spring,spring-boot,oauth-2.0,spring-cloud,spring-cloud-gateway,Spring,Spring Boot,Oauth 2.0,Spring Cloud,Spring Cloud Gateway,如何在Spring Cloud Gateway中配置路由以使用授权授予类型为密码的OAuth2客户端?换句话说,如何将请求中带有令牌的授权头添加到API中?因为我要与遗留应用程序集成,所以必须使用授权类型密码 我有以下申请: @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApp

如何在Spring Cloud Gateway中配置路由以使用授权授予类型为密码的OAuth2客户端?换句话说,如何将请求中带有令牌的授权头添加到API中?因为我要与遗留应用程序集成,所以必须使用授权类型密码

我有以下申请:

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
           .route("route_path", r -> r.path("/**")
                   .filters(f -> f.addRequestHeader("Authorization", "bearer <token>"))
                   .uri("http://localhost:8092/messages"))
           .build();
    }
}
通过此配置,我们可以使用
WebClient
发出请求。这会在调用端点后以某种方式初始化OAuth2客户端:

@GetMapping("/explicit")
public Mono<String[]> explicit() {
    return this.webClient
        .get()
        .uri("http://localhost:8092/messages")
        .attributes(clientRegistrationId("messaging-client-password"))
        .retrieve()
        .bodyToMono(String[].class);
}
最后,通过配置全局筛选器,我们可以修改请求以包含授权标头:

@Bean
public GlobalFilter customGlobalFilter() {
    return (exchange, chain) -> {
        //adds header to proxied request
        exchange.getRequest().mutate().header("Authorization", authorizedClient.getAccessToken().getTokenType().getValue() + " " + authorizedClient.getAccessToken().getTokenValue()).build();
        return chain.filter(exchange);
    };
}
在按顺序运行这三个请求之后,我们可以使用SpringCloudGateway的密码授权

当然,这个过程非常混乱。仍然需要做的是:

  • 获取筛选器内授权客户端的引用
  • 使用
    contextAttributesMapper
  • 将所有这些内容写入过滤器,而不是全局过滤器。实现可以为此提供很好的帮助

  • 我使用
    WebClientHttpRoutingFilter
    实现了授权授予类型:密码

    默认情况下,SpringCloudGateway使用Netty路由过滤器,但有一种替代方法不需要Netty()

    webclienthtproutingfilter
    使用
    WebClient
    路由请求

    WebClient
    可以通过
    ExchangeFilterFunction
    ()配置
    ReactiveOAuth2AuthorizedClientManager
    ReactiveOAuth2AuthorizedClientManager将负责管理访问/刷新令牌,并为您完成所有繁重的工作


    您可以查看此实现。此外,我用这种方法实现了客户端凭据授予

    Hi@rigor你能链接一个示例githhub吗?谢谢
    private OAuth2AuthorizedClient authorizedClient;
    @GetMapping("/token")
    public String token(@RegisteredOAuth2AuthorizedClient("messaging-client-password") OAuth2AuthorizedClient authorizedClient) {
        this.authorizedClient = authorizedClient;
        return authorizedClient.getAccessToken().getTokenValue();
    }
    
    @Bean
    public GlobalFilter customGlobalFilter() {
        return (exchange, chain) -> {
            //adds header to proxied request
            exchange.getRequest().mutate().header("Authorization", authorizedClient.getAccessToken().getTokenType().getValue() + " " + authorizedClient.getAccessToken().getTokenValue()).build();
            return chain.filter(exchange);
        };
    }