4、数据源接入校验

数据源接入校验是实时风控网关的第一道防线,确保上游系统推送的数据在进入风控引擎前已满足格式、完整性、时效性与可信性要求。本节从四个维度展开:上游数据格式校验、字段完整性校验、数据时间戳校验与数据签名校验。

核心原则:网关层只做“格式与可信”校验,不做业务语义判断。任何格式异常、字段缺失、时间偏差或签名失败的数据,应直接拒绝并记录偏差日志,不进入后续规则计算。

4.1 上游数据格式校验

网关必须明确上游系统支持的协议与序列化格式,并在接入点进行严格匹配。常见格式包括 JSON、XML、Protobuf、Avro 等。校验要点如下:

  • 协议头校验:检查 Content-Type 是否与预期一致(如 application/json、application/x-protobuf)。
  • 语法解析:对 JSON 数据执行完整解析,捕获非法字符、未闭合括号、重复键名等异常。
  • 结构约束:验证根节点是否为对象或数组,嵌套层级是否超过预设深度(建议 ≤ 10 层)。
  • 编码校验:强制使用 UTF-8 编码,拒绝 GBK、ISO-8859-1 等非标准编码。
格式类型 校验项 异常处理策略
JSON 语法解析、键名重复、嵌套深度 返回 400 Bad Request,记录原始报文前 1KB
XML DTD/Schema 验证、标签闭合、实体扩展 拒绝并告警,防止 XXE 攻击
Protobuf 消息描述符匹配、字段编号范围 反序列化失败时返回 415 Unsupported Media Type
Avro Schema 兼容性、压缩编码头 记录 Schema ID 并触发降级
工程建议:在网关层维护一个“格式校验器注册表”,每种格式对应一个独立校验器,支持热加载。避免在同一个校验器内写大量 if-else 分支。

4.2 字段完整性校验

字段完整性校验确保上游数据包含风控引擎所需的全部必填字段,且字段值类型、长度、取值范围符合预定义契约。校验流程分为三个步骤:

  1. 必填字段清单比对:从配置中心拉取当前版本的字段契约,逐字段检查是否存在且非空。
  2. 字段类型与格式校验:如 userId 必须为字符串且长度 ≤ 64,amount 必须为数值且 ≥ 0。
  3. 枚举值域校验:对 channel、eventType 等枚举字段,检查是否在允许值列表内。
字段类别 校验规则示例 偏差处理
必填业务字段 userId、transactionId、timestamp 缺失则拒绝,返回 422 Unprocessable Entity
可选扩展字段 deviceFingerprint、ipAddress 缺失时标记为 null,不影响主流程
嵌套对象字段 location.lat、location.lng 部分缺失时按最小可用数据降级
数组字段 items[].sku、items[].quantity 数组为空或元素不完整时拒绝
避坑提示:不要将字段完整性校验与业务规则校验混在一起。例如“金额不能超过 100 万”属于业务规则,应在风控引擎内处理;网关层只检查“金额字段是否存在且为数值”。

4.3 数据时间戳校验

时间戳校验用于防止数据重放攻击、过期数据注入以及时钟偏差导致的乱序问题。网关需同时校验时间戳格式与时间窗口。

  • 格式校验:强制使用 Unix 毫秒时间戳(13 位整数)或 ISO 8601 格式(如 2025-03-21T14:30:00+08:00)。
  • 时间窗口校验:计算网关当前时间与数据时间戳的差值,允许的最大偏差由配置决定(通常为 ±5 分钟)。
  • 顺序校验(可选):对同一上游的连续请求,检查时间戳是否单调递增,防止乱序注入。
// 时间窗口校验伪代码
long currentTime = System.currentTimeMillis();
long dataTime = parseTimestamp(data.get("timestamp"));
long diff = Math.abs(currentTime - dataTime);

if (diff > allowedWindowMs) {
    // 记录偏差:时间戳偏差 = diff ms
    reject("timestamp_out_of_window", "数据时间戳超出允许窗口");
}
时钟同步要求:网关服务器必须启用 NTP 同步,时钟偏差控制在 100ms 以内。建议在网关启动时与上游系统进行一次时间握手,记录双方时钟偏移量。

4.4 数据签名校验

数据签名校验是防止数据在传输过程中被篡改的关键手段。网关需支持对称签名(HMAC-SHA256)与非对称签名(RSA-SHA256、ECDSA)两种模式,并根据上游系统的安全等级选择。

签名算法 密钥管理 适用场景 校验性能
HMAC-SHA256 共享密钥,需定期轮换 内部服务间通信 ~2μs/次
RSA-SHA256 公钥分发,私钥由上游持有 外部合作伙伴接入 ~50μs/次
ECDSA 椭圆曲线密钥对 移动端 SDK 上报 ~30μs/次

签名校验的标准流程:

  1. 从请求头或消息体中提取签名值(通常位于 X-Signature 头)。
  2. 按约定规则拼接待签名字符串(包括 HTTP 方法、路径、时间戳、请求体等)。
  3. 使用对应算法与密钥重新计算签名,并与提取值进行常量时间比较。
  4. 校验失败时,记录签名偏差详情(如算法不匹配、密钥版本错误、签名过期),并返回 401 Unauthorized。
// 签名校验示例(HMAC-SHA256)
String payload = method + "\n" + path + "\n" + timestamp + "\n" + body;
String expectedSignature = HmacUtils.hmacSha256Hex(secretKey, payload);
String actualSignature = request.getHeader("X-Signature");

if (!MessageDigest.isEqual(
        expectedSignature.getBytes(StandardCharsets.UTF_8),
        actualSignature.getBytes(StandardCharsets.UTF_8))) {
    // 记录偏差:签名校验失败
    reject("signature_mismatch", "签名不匹配");
}
安全增强:建议在签名校验中加入 nonce(一次性随机数)与 timestamp 字段,防止重放攻击。网关应维护一个最近 5 分钟的 nonce 缓存,拒绝重复 nonce。
数据源接入校验流程 上游数据到达 ① 上游数据格式校验 ② 字段完整性校验 ③ 数据时间戳校验 ④ 数据签名校验 校验通过 → 进入风控引擎 拒绝并记录偏差 任意一项校验失败 立即拒绝,不进入下一阶段

4.5 偏差记录与告警

所有校验失败的数据必须生成结构化的偏差记录,包含以下字段:

字段 说明 示例值
deviationId 全局唯一偏差 ID dev-20250321-001234
checkpoint 校验阶段标识 format_check、signature_check
errorCode 错误码 FIELD_MISSING、TIMESTAMP_EXPIRED
rawDataPreview 原始数据前 256 字符 {"userId":"u123","amount":...
timestamp 偏差发生时间 2025-03-21T14:30:00.123Z
告警阈值建议:当同一上游在 1 分钟内连续出现 5 次以上签名校验失败时,触发 P1 级告警,自动通知安全运维团队。格式校验失败超过 10 次/分钟时,触发 P2 级告警,提示上游系统可能存在兼容性问题。