项目要使用到spring cloud gateway进行验签,由于国内用webflux 相对还是较少,作以记录。
import cn.yto.collect.common.util.JacksonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.io.IOException;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
public class AuthSignGatewayFilterFactory extends AbstractGatewayFilterFactory {
public AuthSignGatewayFilterFactory() {
super(AuthSignGatewayFilterFactory.Config.class);
}
static class Config {
}
private static final String CONTENT_TYPE = "Content-Type";
private static final String CONTENT_TYPE_JSON = "application/json";
@Override
public GatewayFilter apply(Object config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
String contentType = request.getHeaders().getFirst(CONTENT_TYPE);
String method = request.getMethodValue();
if (null != contentType && HttpMethod.POST.name().equalsIgnoreCase(method) && contentType.contains(CONTENT_TYPE_JSON)) {
ModifyRequestBodyGatewayFilterFactory.Config modifyRequestConfig = new ModifyRequestBodyGatewayFilterFactory.Config()
.setContentType(CONTENT_TYPE_JSON)
.setRewriteFunction(String.class, String.class, (exchange1, originalRequestBody) -> {
Map<String, Object> map = null;
try {
map = JacksonUtil.from(originalRequestBody, Map.class);
} catch (IOException e) {
e.printStackTrace();
}
String appId = String.valueOf(map.get("appId"));
String json = String.valueOf(map.get("json"));
boolean isPass = validateApiPermission(exchange1, originalRequestBody);
if (!isPass) {
throw new RuntimeException("500");
}
return Mono.just(json);
});
return new ModifyRequestBodyGatewayFilterFactory().apply(modifyRequestConfig).filter(exchange, chain);
}
if (HttpMethod.GET.name().equalsIgnoreCase(method)) {
Map<String, Object> query = request.getQueryParams().entrySet()
.stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue
));
boolean isPass = validateApiPermission(exchange, "");
if (!isPass) {
throw new RuntimeException("query");
}
return chain.filter(exchange.mutate().request(request).build());
}
return chain.filter(exchange);
};
}
@Override
public String name() {
return "AuthSign";
}
/**
* verify users authority
*
* @param exchange
* @param requestParameters
* @return
*/
private boolean validateApiPermission(ServerWebExchange exchange, String requestParameters) {
log.debug("request params :{}", requestParameters);
/***to do
*
*/
return true;
}
}
# 应用名称
spring:
application:
name: log-gateway
cloud:
gateway:
routes:
- id: webpage
uri: http://localhost:9998
predicates:
- Path=/api/collect/business-log/**
filters:
- AuthSign
注意,filters的AuthSign对应的filter中的name方法。
贴上寻找答案的链接:
https://github.com/spring-cloud/spring-cloud-gateway/issues/747
https://medium.com/@xuezhongyu01/spring-cloud-gateway-read-and-modify-request-body-9796e759c965