我试图在调用REST服务之前添加自定义过滤器。在下面的此类中,我试图在HttpRequest中添加自定义过滤器,但出现错误:-
java.lang.UnsupportedOperationException:空 在java.util.Collections $ UnmodifiableMap.computeIfAbsent(Collections.java:1535)〜[na:1.8.0_171] 在org.springframework.util.CollectionUtils $ MultiValueMapAdapter.add(CollectionUtils.java:459)〜[spring-core-5.0.7.RELEASE.jar:5.0.7.RELEASE]
public class AuthenticationWebFilter implements WebFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(AuthenticationWebFilter.class);
@Autowired
private TokenServiceRequest tokenServiceRequest;
@Autowired
private AuthenticationProvider authenticationProvider;
public AuthenticationWebFilter(TokenServiceRequest tokenServiceRequest, AuthenticationProvider authenticationProvider) {
super();
this.tokenServiceRequest = tokenServiceRequest;
this.authenticationProvider = authenticationProvider;
}
@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
HttpHeaders requestHeaders = serverWebExchange.getRequest().getHeaders();
HttpHeaders responseHeaders = serverWebExchange.getResponse().getHeaders();
LOGGER.info("Response HEADERS: "+responseHeaders);
LOGGER.info("Request HEADERS: "+serverWebExchange.getRequest().getHeaders());
tokenServiceRequest.setUsername(serverWebExchange.getRequest().getHeaders().getFirst(CommerceConnectorConstants.USERNAME));
tokenServiceRequest.setPassword(serverWebExchange.getRequest().getHeaders().getFirst(CommerceConnectorConstants.PASSWORD));
tokenServiceRequest.setClientId(serverWebExchange.getRequest().getHeaders().getFirst(CommerceConnectorConstants.CLIENT_ID));
tokenServiceRequest.setSecretClient(serverWebExchange.getRequest().getHeaders().getFirst(CommerceConnectorConstants.SECRET_CLIENT));
LOGGER.info("Token Received: " + authenticationProvider.getUserAccessToken(tokenServiceRequest).getTokenId());
//responseHeaders.set(CommerceConnectorConstants.X_AUTH_TOKEN, authenticationProvider.getUserAccessToken(tokenServiceRequest).getTokenId());
//responseHeaders.add(CommerceConnectorConstants.X_AUTH_TOKEN, authenticationProvider.getUserAccessToken(tokenServiceRequest).getTokenId());
//This below code is not working
serverWebExchange.getRequest().getQueryParams().add("test", "value");
//This below code is not working
//serverWebExchange.getRequest().getHeaders().add(CommerceConnectorConstants.X_AUTH_TOKEN, authenticationProvider.getUserAccessToken(tokenServiceRequest).getTokenId());
LOGGER.info("Exiting filter@AuthenticationWebFilter");
return webFilterChain.filter(serverWebExchange);
}
}
在HTTPResponse中,我可以设置自定义标头,但我的要求是在HTTPRequest中添加自定义标头。请告知。
答案 0 :(得分:4)
如果您在Spring Cloud Gateway中,则可以通过实现GlobalFilter或GatewayFilter修改请求标头。
@Component
public class LogFilter implements GlobalFilter, Ordered {
private Logger LOG = LoggerFactory.getLogger(LogFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(
exchange.mutate().request(
exchange.getRequest().mutate()
.header("customer-header", "customer-header-value")
.build())
.build());
}
@Override
public int getOrder() {
return 0;
} }
如果您在ZuulFilter中,则addZuulRequestHeader可以修改请求标头。
RequestContext.getCurrentContext().addZuulRequestHeader("customer-header", "customer-header-value");
希望有帮助。
答案 1 :(得分:0)
我认为出于安全原因引发了异常。如果过滤器可以添加/修改HTTP请求标头,那就太麻烦了。当然,您可以通过创建一系列装饰器来实现此目的:
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.ServerWebExchangeDecorator;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
public class CustomFilter implements WebFilter {
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
ServerWebExchangeDecorator decorator = new ServerWebExchangeDecoratorImpl(serverWebExchange);
//do your stuff using decorator
return webFilterChain.filter(decorator);
}
}
class ServerWebExchangeDecoratorImpl extends ServerWebExchangeDecorator {
private ServerHttpRequestDecorator requestDecorator;
public ServerWebExchangeDecoratorImpl(ServerWebExchange delegate) {
super(delegate);
this.requestDecorator = new ServerHttpRequestDecoratorImpl(delegate.getRequest());
}
@Override
public ServerHttpRequest getRequest() {
return requestDecorator;
}
}
class ServerHttpRequestDecoratorImpl extends ServerHttpRequestDecorator {
// your own query params implementation
private MultiValueMap queryParams;
public ServerHttpRequestDecoratorImpl(ServerHttpRequest request) {
super(request);
this.queryParams = new HttpHeaders();
this.queryParams.addAll(request.getQueryParams());
}
@Override
public MultiValueMap<String, String> getQueryParams() {
return queryParams;
}
//override other methods if you want to modify the behavior
}
答案 2 :(得分:0)
public class CustomTokenFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
ServerHttpRequest mutateRequest = serverWebExchange.getRequest().mutate()
.header("token", "test")
.build();
ServerWebExchange mutateServerWebExchange = serverWebExchange.mutate().request(mutateRequest).build();
return webFilterChain.filter(mutateServerWebExchange);
}
}
答案 3 :(得分:0)
我遇到了同样的问题,因为标题已经具有相同的密钥;我的解决办法是在header里面设置key,先检查key是否存在;
@Configuration
public class AuthGatewayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
Consumer<HttpHeaders> httpHeaders = httpHeader -> {
// check exists
if(StringUtils.isBlank(httpHeader.getFirst("xxx"))){
httpHeader.add("xxx", "xxx");
}
};
ServerHttpRequest serverHttpRequest = exchange.getRequest().mutate().headers(httpHeaders).build();
exchange = exchange.mutate().request(serverHttpRequest).build();
return chain.filter(exchange);
}
}