Reputation: 373
I am kind of new to the Spring reactor programming and currently I have encounter a requirement, which need to validate Authorization header within the spring GatewayFilterChain
which I have created a "AuthenticationFilter" with code snippet:
public class AuthenticationFilter implements GlobalFilter {
@Autowired
private WebClient.Builder webClientBuilder;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//Do API call to auth the "Authorization" Header data from the request
AuthHeaderDto authHeaderDto = retrieveHeaderDto(exchange.getRequest());
Mono<AuthResponse> monoAuthResponse = webClientBuilder.build().post()
.uri(uri)
.body(BodyInserters.fromPublisher(Mono.just(authHeaderDto), AuthHeaderDto.class))
.retrieve()
.bodyToMono(AuthResponse.class);
//TODO: base on monoAuthResponse(parameter "isValid":true/false)
// to set different status code (401 for false, 200 for true) to ServerWebExchange
// and continue the filter chain, i.e., return chain.filter(exchange);
}
}
My Question is that the continue process of the chain actually need to wait for the validation request (i.e., blocking), in this context, in what way I can achieve that?
Thanks a lot for the help.
Upvotes: 0
Views: 1242
Reputation: 2277
You can do something like this. Its not tested though.
@Component
public class GlobalGatewayPreFilter extends AbstractGatewayFilterFactory<GlobalGatewayPreFilter.Config> {
private final WebClient client;
@Autowired
public GlobalGatewayPreFilter() {
super(Config.class);
this.client = WebClient.create("http://blahblah");
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) ->
exchange.getPrincipal()
.filterWhen(authenticationToken -> checkAuth(exchange))
.map(authenticationToken -> exchange)
.switchIfEmpty(Mono.defer(() -> setErrorResponse(exchange.getResponse()).setComplete().then(Mono.empty())))
.flatMap(chain::filter);
}
private ServerHttpResponse setErrorResponse(ServerHttpResponse serverHttpResponse) {
serverHttpResponse.setStatusCode(HttpStatus.UNAUTHORIZED);
return serverHttpResponse;
}
private Mono<Boolean> checkAuth(ServerWebExchange exchange) {
if (!exchange.getRequest().getHeaders().containsKey("Authorization")) {
return Mono.empty();
}
// Map your response and send true false
return Mono.just(true);
}
public static class Config {
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
}
However I do not recommend doing this kind of Auth check in here. I would rather use Spring Security to do this but its up to you.
Upvotes: 1