网络验证原理
「网络验证」是指软件在启动或运行过程中,通过网络向授权服务器确认「当前使用者是否有权使用本软件」。相比本地注册码,网络验证的优势是:授权状态可以随时被回收、可以按时间/次数计费、可以绑定设备防止一码多用。
本页解释 A7验证的整体链路,帮助你理解每个 API 调用背后发生了什么。
整体链路
text
┌─────────────┐ ┌──────────────────┐
│ 你的客户端 │ │ A7验证 服务端 │
└──────┬──────┘ └────────┬─────────┘
│ 1. Init: AppId + AppKey + TimeStamp + Sign │
├─────────────────────────────────────────────────►│
│ │ 校验 AppId 是否存在 → 1001
│ │ 校验 AppKey 是否匹配 → 1011
│ │ 校验程序审核状态 → 1012
│ │ 校验时间戳 ±300s → 1014
│ │ 校验 Sign → 1010
│ 2. 返回 api_password │
│◄─────────────────────────────────────────────────┤
│ │
│ 3. Handle: TimeStamp + Data(RC4密文) + Sign │
├─────────────────────────────────────────────────►│
│ │ 由 ApiPassword 定位程序 → 1001
│ │ 校验时间戳 / Sign
│ │ RC4 解密 Data → 明文参数
│ │ 按 action 分发业务 → 1015
│ 4. 返回业务 JSON │
│◄─────────────────────────────────────────────────┤为什么是两步
如果只有一步(每次都带 AppKey),那么:
AppKey会在每一次网络请求中出现,抓包成本极低。AppKey一旦泄露,攻击者可以无限次伪造任意请求。
两步模型把「长期凭据」和「工作密钥」分开:
| 长期凭据 | 工作密钥 | |
|---|---|---|
| 名称 | AppKey | ApiPassword |
| 出现频率 | 只在 Init 时 | 每次业务请求 |
| 泄露后果 | 严重,需重置 AppKey | 可在后台一键重置,客户端重新 Init 即可 |
| 存放位置 | 客户端二进制(混淆存放) | 仅内存 |
服务端的校验顺序
理解校验顺序有助于快速定位错误码。
Init 阶段
- 四个参数(
AppId/AppKey/TimeStamp/Sign)是否齐全 → 缺则1013 TimeStamp与服务器时间差是否在 ±300 秒内 → 超出则1014AppId能否找到对应程序 → 找不到则1001AppKey是否与程序密钥一致 → 不一致则1011- 程序状态是否为
approved→ 否则1012 Sign是否等于MD5(AppId + AppKey + TimeStamp + AppKey)→ 否则1010- 全部通过 → 返回
data.api_password
注意校验顺序
AppKey 的校验(第 4 步)早于 Sign 的校验(第 6 步)。所以 AppKey 抄错时你会先看到 1011 而不是 1010。
Handle 阶段
- 从请求头
X-Api-Password/ 表单ApiPassword/ URL 路径中取出接口密码 - 用它定位程序 → 找不到则
1001 - 程序状态是否为
approved→ 否则1012 TimeStamp与Sign是否齐全 → 缺则1013- 时间戳窗口 ±300 秒 → 超出则
1014 Sign是否等于MD5(ApiPassword + TimeStamp + Data)→ 否则1010- RC4 解密
Data,按&与=解析成参数表 - 读取
action并分发;不在 12 个 action 之列 →1015 - 执行具体业务逻辑,返回结果
两种验证模式
A7验证同时支持卡密模式和用户账号模式,同一个程序可以两种都开。
卡密模式
text
Init → SingleLogin(Card + Mac) → 拿 token → UserHeartbeat(Type=card)- 用户不需要注册,直接输入卡密。
- 首次使用时卡密自动激活并绑定当前机器码(创建
Activation记录)。 - 同一张卡在另一台机器上使用会新建一条激活记录(受卡密的设备数策略约束)。
- 支持按次卡:
is_times = true,每次SingleLogin消耗一次,返回total/used/remaining。
用户账号模式
text
Init → UserRegin → UserLogin(UserName + Password) → 拿 token → UserHeartbeat(Type=user)- 用户注册用户名 + 密码;卡密变成「充值凭证」。
- 账号与机器码绑定:换电脑时
UserLogin会返回1022,需走ChangeBind换绑。 - 支持 QQ 扫码登录(
LoginType=qq)。 - 续期用
UserRecharge(无需密码)或UserLogin时附带Card。
两种模式对照
| 维度 | 卡密模式 | 用户账号模式 |
|---|---|---|
| 登录接口 | SingleLogin | UserLogin |
心跳 Type | card | user |
| 是否需注册 | 否 | 是(UserRegin) |
| 续期方式 | 重新 SingleLogin 新卡 | UserRecharge |
| 换设备 | 卡密策略决定 | ChangeBind |
| 支持按次卡 | ✅ | ❌(返回 1024) |
| 支持 QQ 登录 | ❌ | ✅ |
| 找回授权 | 靠用户自己保管卡密 | 靠用户名密码 |
数据模型(服务端视角)
| 概念 | 说明 |
|---|---|
| Product(程序) | 你在控制台创建的软件,持有 AppId / AppKey / ApiPassword |
| License(卡密) | 一串授权码,有类型(时长卡 / 按次卡)、状态、到期时间 |
| EndUser(终端用户) | 你的软件的使用者。卡密模式下按机器码自动创建;账号模式下由 UserRegin 创建 |
| Activation(激活记录) | 一次「卡密 × 设备」的绑定,记录到期时间、状态、最后心跳时间 |
| VerifyLog(验证日志) | 只有 SingleLogin 和 UserLogin 会计入验证统计 |
只有登录计入统计
后台的「验证次数」统计只统计 SingleLogin 和 UserLogin。心跳、查询类接口不计数,可以放心高频调用(但仍建议心跳 5 分钟一次)。
客户端应该怎么用
一个健壮的客户端集成大致长这样:
- 启动时:
Init→GetLatestVersion(检查更新)→GetBulletin(拉公告) - 登录时:
SingleLogin或UserLogin,成功后把token存在内存 - 运行中:定时器每 5 分钟
UserHeartbeat,收到msg非空时弹窗展示 - 心跳失败:
1005到期 /1006封停 /1007Token 失效 → 退出核心功能并提示 ApiPassword失效(1001):静默重新Init后重试一次
不要只在启动时验证一次
只在启动时验证的软件,很容易被「断网后继续运行」绕过。请务必用心跳持续校验,并且在心跳失败时真正禁用核心功能。参见 防重放攻击实战。