使用 RouteLocatorBuilder 授权 REST 调用

Authorizing the REST calls with RouteLocatorBuilder

背景

我的用例是使用网关对调用进行身份验证。我假设所有调用都必须有 user_idtoken。我有一个 API,在检查它是否是一个有效请求后,它会同时接受 user_id、令牌和 return 一个布尔值。

当前工作

我已经编写了一个网关配置,它在将 API 路由到相关 micro-service 时工作正常,但它在身份验证方面工作不正常。

工作代码,

@Configuration
public class RouteConfig {
 @Bean
    public RouteLocator myRoutes(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("path_route", r -> r.path("app1/**")
                        .filters(f -> f.rewritePath("app1/(?<segment>.*)",
                                "app1/${segment}"))
                        .uri("http://localhost:8099"))
                .build();
    }
}

首先,我需要获取 Headers 变量,然后对 API 进行 POST 调用,其中 return 是 BOOLEAN 响应。如果它是真的那么上面的代码应该调用。否则呼叫应该被拒绝。

试图获得 Headers 值

@Configuration
public class RouteConfig {
 @Bean
    public RouteLocator myRoutes(RouteLocatorBuilder builder,@RequestHeader("user_id")
            String userId,@RequestHeader("token")
            String token) {

System.out.println(userId);
System.out.println(token);

        return builder.routes()
                .route("path_route", r -> r.path("app1/**")
                        .filters(f -> f.rewritePath("app1/(?<segment>.*)",
                                "app1/${segment}"))
                        .uri("http://localhost:8099"))
                .build();
    }
}

但是它不工作并且应用程序崩溃了。

您可以实施 GatewayFilter 来检查网关上的每个请求。

@Component
public class AuthFilter implements GatewayFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();

        HttpHeaders headers = request.getHeaders();
        if (!headers.containsKey("user_id") || !headers.containsKey("token"))
            return this.onError(exchange, HttpStatus.UNAUTHORIZED);

        String userId = request.getHeaders().getOrEmpty("user_id").get(0);
        String token = request.getHeaders().getOrEmpty("token").get(0);

        Map<String, String> body = new HashMap<>();
        body.put("user_id", userId);
        body.put("token", token);
        WebClient client = WebClient.builder().build();
        boolean ok = client
                .post()
                .uri("your/auth/api")
                .body(Mono.just(body), Map.class)
                .retrieve()
                .bodyToFlux(Boolean.class)
                .blockFirst();

        if (!ok)
            return this.onError(exchange, HttpStatus.UNAUTHORIZED);

        return chain.filter(exchange);
    }

    private Mono<Void> onError(ServerWebExchange exchange, HttpStatus httpStatus) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(httpStatus);
        return response.setComplete();
    }
}

并将过滤器应用于您的路线配置。不确定配置是否正确以及重写是否正确应用。

@Configuration
public class RouteConfig {

    @Autowired
    private AuthFilter filter;

    @Bean
    public RouteLocator routes(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("path_route", r -> r.path("app1/**")
                        .filters(f -> f.filters(filter).rewritePath("app1/(?<segment>.*)",
                                "app1/${segment}"))
                        .uri("http://localhost:8099"))
                .build();
    }

}

请注意,此代码未经测试,只是为了让您了解如何解决您的问题。