Skip to content

未设置标题

WARNING

  • 由claude生成

介绍

cap.js 是一款开源的、十分简单的人机校验方案,同时功能也比较完善。

本来也一直想做类似 reCaptcha 的人机校验功能,正好无意中刷到了这个项目,一看仓库作者也是很用心,而且是完全开源的,就决定尝试一下。

后端可以像我一样集成到项目中,也有一个 standalone 的版本。社区也有各种版本,java/go/python 等等,都可以前去尝试。

项目默认是全局的 cap token guard 守卫的,如果有不重要的公共接口就做 cap token free 处理,也就是添加一个 cap token free 的 guard。

相关链接

流程图

mermaid
sequenceDiagram
    participant Client as 客户端<br/>(浏览器)
    participant Guard as CAP Guard<br/>(WalnutAdminGuardCap)
    participant Cache as Redis缓存
    participant Lock as MurLock<br/>(分布式锁)
    participant CapAPI as CapJS API<br/>(第三方)
    participant Challenge as Challenge<br/>State Service

    Note over Client,Challenge: 每个请求都会执行 CAP Guard

    Client->>Guard: HTTP 请求<br/>(携带 capToken Cookie)
    activate Guard

    Note over Guard: Step 1: 检查是否跳过
    Guard->>Guard: 检查 @WalnutAdminGuardCapFree()<br/>或 Postman 请求

    alt 需要跳过验证
        Guard-->>Client: 跳过验证,直接通过
    end

    Note over Guard: Step 2: 读取风险决策
    Guard->>Guard: 读取 request.risk.comprehensive<br/>.recommendation

    alt 无风险评估数据
        Guard-->>Client: 警告并允许通过
    end

    Note over Guard: Step 3: CAP Token 硬校验
    Guard->>Guard: 获取 Cookie 中的 capToken

    alt Token 缺失
        alt shouldChallenge = true
            Guard-->>Client: 40116 Interaction Required<br/>(需要明确交互)
        else shouldChallenge = false
            Guard-->>Client: 40117 Refresh Required<br/>(无感刷新)
        end
    end

    Note over Guard,Cache: Token 存在,验证有效性
    Guard->>Cache: getCapTokenCache(deviceId)

    alt 缓存命中
        Cache-->>Guard: 返回缓存结果 (true/false)
        Guard->>Guard: 快速路径验证通过
    else 缓存未命中
        Guard->>Lock: 请求分布式锁<br/>Key: CAP:{deviceId}
        Lock-->>Guard: 获取锁成功 (3s 超时)

        Note over Guard: Double-Check 模式
        Guard->>Cache: 再次检查缓存<br/>(防止并发重复验证)

        alt Double-Check 缓存命中
            Cache-->>Guard: 返回缓存结果
        else 缓存仍未命中
            Guard->>CapAPI: AppCapJS.validateToken(capToken)
            activate CapAPI
            CapAPI-->>Guard: { success: true/false }
            deactivate CapAPI

            alt 验证失败
                Guard-->>Client: 40111 You Are Bot<br/>(判定为机器人)
            else 验证成功
                Guard->>Cache: setCapTokenCache(deviceId)<br/>(缓存验证结果)
                Cache-->>Guard: 缓存成功
            end
        end

        Guard->>Lock: 释放分布式锁
    end

    Note over Guard: Step 4: 标记 Critical Factors
    Guard->>Challenge: markChallengeHandled()<br/>批量标记所有 criticalFactors
    activate Challenge
    Challenge->>Challenge: 根据 userId 自动区分<br/>Pre Auth / Post Auth 因子
    Challenge-->>Guard: 标记成功
    deactivate Challenge

    Guard-->>Client: 验证通过,继续执行业务逻辑
    deactivate Guard

    Note over Client: 请求进入 Controller 层

基于 MIT 许可发布