java - Spring Cloud Gateway - 审计日志
问题描述
我想将每个请求/响应记录到数据库(例如 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。感谢任何建议。
解决方案
推荐阅读
- mongodb - NestJS MongoDB 验证器不起作用
- javascript - 获取数字列表的“排行榜”
- handlebars.js - 按长度 -1 获取 Handlebars 中数组的最后一个元素
- .net - C# 中 AWSConfigs.GetConfig 的示例
- anylogic - 将模型从 mac 复制到 windows pc 时出错
- javascript - 按值对地图进行排序,其中地图是 JavaScript 中的数组
- javascript - 使用 blob (react) 创建文件时出错:对象必须具有可调用的 @@iterator 属性
- java - 在 Spring 的响应体内返回 2 个对象的最佳方法
- html - 布尔玛中心柱,但在底部粘上额外的柱子
- c++ - 替换 to_utf8string 以确保在 C++ DLL 中的 Windows 7 上正确的字符串编码