我想将每个请求/响应记录到数据库(例如MongoDB)中。由于找不到现有的类似于审核的过滤器,因此我编写了一个简单的过滤器,如下所示:
@Component
@Slf4j
@AllArgsConstructor
public class AuditFilter extends AbstractGatewayFilterFactory {
private static final String NOT_APPLICABLE = "[Not applicable]";
private static final String X_REAL_IP = "X-Real-IP";
private static final String X_FORWARDED_FOR = "X-Forwarded-For";
private final AuditProperties properties;
private final ReactiveMongoTemplate mongoOps;
@Override
public GatewayFilter apply(Object config) {
if (!properties.isEnabled()) {
return (exchange, chain) -> chain.filter(exchange);
}
return ((exchange, chain) -> chain.filter(exchange)
.then()
.doOnSubscribe(t -> {
createAuditLog(exchange).subscribe();
}));
}
private Mono<AuditLogPO> createAuditLog(ServerWebExchange exchange) {
log.info("写入MongoDB");
Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
String serviceId = Objects.requireNonNull(route).getId();
AuditLogPO entity = new AuditLogPO();
entity.setServiceId(serviceId);
entity.setStartTimestamp(null);//TODO how to obtain?
entity.setSourceIp(getRealIp(request));
entity.setRequestUri(request.getURI().toString());
entity.setRequestBody(NOT_APPLICABLE);//TODO how to obtain?
if (request.getMethod() != null) {
entity.setRequestMethod(request.getMethod().name());
}
entity.setRequestHeaders(request.getHeaders());
entity.setResponseHeaders(response.getHeaders());
entity.setResponseBody(NOT_APPLICABLE);//TODO how to obtain?
entity.setStatusCode(null == response.getStatusCode() ? HttpStatus.FORBIDDEN.value() : response.getStatusCode().value());
entity.setEndTimestamp(new Date());
return mongoOps.insert(entity);
}
/**
* 获取请求的源IP
*/
private String getRealIp(ServerHttpRequest request) {
HttpHeaders headers = request.getHeaders();
String realIp;
if (headers.containsKey(X_REAL_IP)) {
realIp = String.valueOf(headers.getFirst(X_REAL_IP));
} else if (headers.containsKey(X_FORWARDED_FOR)) {
realIp = String.valueOf(headers.getFirst(X_FORWARDED_FOR));
} else {
realIp = request.getRemoteAddress() != null ?
(request.getRemoteAddress().getAddress() != null ?
request.getRemoteAddress().getAddress().getHostAddress() : "") : "";
}
return realIp;
}
}
如您所见,我在获取这些数据方面遇到了麻烦: requestStartTime , requestBody , responseBody 。感谢任何建议。