Skip to content

认证与会话

本文档详细说明 AuthNexus 的认证流程、Token 管理机制、会话生命周期以及多设备处理策略。

认证流程概览

AuthNexus 的认证流程是一个多层安全验证过程,从 TLS 传输层到业务层逐级校验。

完整认证时序

SDK Client                    server_app                   control_plane_app
    │                              │                              │
    ├──── TCP 连接 ────────────────►│                              │
    │                              │                              │
    ├──── mTLS 握手 ──────────────►│                              │
    │     (CA 链 + EKU + SAN)      │                              │
    │◄─── 握手完成 ────────────────┤                              │
    │                              │                              │
    ├──── 登录请求 ────────────────►│                              │
    │     (app_id + username       │                              │
    │      + password)             │                              │
    │                              ├──── 密码验证(本地DB) ────────►│
    │                              │◄─── 验证结果 ────────────────┤
    │                              │                              │
    │                              ├──── 签发 Token ──────────────│
    │◄─── 登录成功 + Token ────────┤                              │
    │                              │                              │
    ├──── 业务请求(携带 Token) ───►│                              │
    │◄─── 响应 ────────────────────┤                              │

第一层:mTLS 握手

SDK 连接 server_app 时,TLS 握手承担四道约束验证:

  1. CA 信任链:客户端证书必须由受信的 app_client_ca 签发
  2. 证书语义:证书包含 clientAuth EKU(Extended Key Usage)
  3. 应用绑定:证书 SAN 中包含 urn:authnexus:app:<id> URI,标识所属应用
  4. CP 绑定:证书信息在 app_mtls_trust_bundle / app_cert_bindings 中注册

TIP

mTLS 不仅验证身份,还在传输层建立了应用隔离边界。证书中的 app_id 与后续登录请求中的 claimed app_id 必须一致。

第二层:OCSP Stapling 验证

如果节点证书标记了 must-staple:

  • 节点在 TLS 握手时附带 OCSP Response(从 Channel 4 获取)
  • SDK 验证 OCSP Response 签名(使用 ocsp_signer_ca.pem)、时间窗口(maxsec=1800s)与证书状态
  • 无有效 staple 时 SDK 直接拒绝握手

第三层:业务登录

mTLS 握手成功后,SDK 发送登录请求(自定义二进制协议,非 HTTP):

cpp
// SDK 侧(伪代码)
AuthRequest request;
request.app_id = 1001;
request.username = "user@example.com";
request.password = "user_password";
auto result = sdk.login(request);

服务端验证流程:

  1. 确认 claimed app_id 与 mTLS 证书中的 app_id 一致
  2. 在本地 Runtime DB 中查找用户
  3. 使用 HMAC-SHA256 验证密码哈希
  4. 检查用户状态(是否被禁用、黑名单等)
  5. 检查当前认证 Epoch 是否有效
  6. 签发 Token 并创建会话

Token 管理

Token 生成

AuthNexus 使用高速版本化 HMAC-SHA256 Token 方案:

  • 格式$authnexus-fast-hmac-sha256$v=1$<salt_hex>$<hash_hex>
  • Salt:16 字节随机数
  • Hash:32 字节 HMAC-SHA256
  • 域分离:使用 AuthNexusPasswordFastHashV1 字符串

设计取舍

选择 HMAC-SHA256 而非 Argon2/bcrypt/scrypt 是有意为之的设计决策。AuthNexus 优先保证在线高吞吐与低延迟(验证耗时 < 0.5ms),而非离线抗暴力破解。业务场景中的安全性由 mTLS + OCSP + Epoch 等多层机制共同保障。

Token 验证

Token 验证在 server_app 本地完成,不需要访问 CP:

  • 验证耗时 < 0.5ms
  • crypto_threads 线程池中执行,不阻塞 IO 或 Logic 线程
  • 验证失败立即断开连接

会话生命周期

会话创建

登录成功后创建会话对象,包含:

  • 用户 ID 与应用 ID
  • Token
  • 创建时间与过期时间
  • 客户端 IP 与设备信息
  • 当前认证 Epoch

心跳维持

SDK 内置心跳线程自动维持会话活性:

SDK (heartbeat_thread) ──── 心跳包 ────► server_app
                           ◄──── 心跳响应 ────
  • 心跳间隔可配置(通过 server_runtime_settings
  • 服务端更新会话最后活跃时间
  • 连续多次心跳超时视为会话断开

会话超时与清理

超时类型默认行为触发条件
空闲超时断开连接超过指定时间无心跳
绝对超时强制注销会话总时长超过上限
Token 过期拒绝请求Token 的有效期已过

会话清理由 TaskScheduler(BackgroundRuntime 中的后台服务)定期执行,清除过期会话并释放资源。

会话状态安全性

Session 状态 mutation 在任意线程都安全(Session 内部 mutex 保护)。单个 session 的串行访问由 connection.hread_loopawait dispatch 自然保证。

多设备会话处理

同一用户可以从多个设备同时登录,每个设备独立维护会话:

  • 每个连接对应独立的 Session 对象
  • Token 不在设备间共享
  • 应用策略(app_policy)可配置单用户最大同时在线设备数
  • 超出设备数限制时,最早的会话会被踢出

认证 Epoch 机制

Epoch 是 AuthNexus 的全局会话失效机制,用于紧急安全场景。

Epoch 工作原理

管理员触发 Epoch Bump


Control Plane 更新 Epoch 值

        ├──── Channel ② SSE hint: epoch.bumped ────► server_app
        │                                                │
        │                                                ▼
        ├──── Channel ③ Delta Puller 拉取 ───────► auth_epoch_changes


                                                  所有旧 Epoch 会话失效
                                                  用户需重新登录

Epoch 应用场景

  • 密钥泄露:怀疑 Token 签名密钥被泄露时,bump epoch 立即失效所有会话
  • 安全事件:检测到大规模异常登录时,强制全员重新认证
  • 系统维护:需要所有客户端重新建立连接时

Epoch 同步机制

Epoch 变更通过两条路径同步到节点:

  1. 快路径:Channel 2 SSE 推送 epoch.bumped hint,节点立即拉取
  2. 慢路径:Channel 3 Delta Puller 定期拉取 auth_epoch_changes

两条路径互为备份,SSE 健康时 5s/30s 间隔,SSE 降级时 Delta Puller 切换到 800ms/5000ms 快速轮询。

用户与应用的关系

首次卡密登录绑定

用户与应用的归属关系在 首次卡密登录 时建立,而非最后充值时:

  • 用户首次使用某应用的卡密成功登录后,该用户归属于该应用
  • 归属关系一旦建立不可变更
  • 此设计确保代理佣金计算的确定性

多租户隔离

应用作为租户边界,不同应用的用户完全隔离:

  • 用户数据按 app_id 分区
  • Token 仅在对应应用上下文中有效
  • 跨应用访问在协议层被拒绝(mTLS 证书 SAN 校验)

平台管理员 vs 应用代理

两类角色的认证存在差异:

特性平台管理员 (platform_admin)应用代理 (app_agent)
agents.kindplatform_adminapp_agent
app_idNULL(全局)引用真实 application
登录入口Admin 后台Admin 后台
权限范围全平台所有应用仅授权应用集合
应用绑定agent_app_grants
认证方式Admin API TokenAdmin API Token

平台管理员通过 app_id IS NULL 标识,应用代理通过 agent_app_grants 多对多关系绑定到一个或多个应用。Schema 层的 CHECK 约束 + FK ON DELETE RESTRICT + partial UNIQUE 三道防线确保数据一致性。

黑名单机制

服务端维护本地黑名单,用于即时阻断:

  • 黑名单以本地 DB 为单一真相
  • 通过 Delta Puller(Channel 3)从 CP 同步 server_blacklist_changes
  • 黑名单检查在登录与请求处理的 fast path 上执行
  • 命中黑名单的连接立即断开