3

我想将每个请求/响应记录到数据库(例如 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;
    }
}

如您所见,我在如何获取这些数据方面遇到了麻烦:requestStartTimerequestBodyresponseBody。感谢任何建议。

4

0 回答 0