管理员后台 · 配置策略与服务器绑定 · 授权码自助管理
| 场景 | 接口与实现 |
|---|---|
| Windows/Android 软件按设备售卖 | activate 首次占用设备名额,verify/heartbeat 验证,deactivate 主动解绑。账户+设备为绑定单位。 |
| Web 应用 / SaaS | 推荐在后端保存授权码,使用部署实例 ID 验证,后端执行功能限制。浏览器直接验签只能做展示,不能充当收费权限的唯一保护。 |
| 运营方应用配置、游戏区服分发 | bootstrap 返回签名服务器配置,不占玩家设备名额;app_config 可返回 API 地址、功能开关等自定义 JSON。 |
公钥需要通过可信部署固定到客户端。下载地址:RSA 公钥 PEM。不要每次联网下载公钥代替固定公钥信任。
| 字段 | 示例 | 用途 |
|---|---|---|
| product_id | 2 | 产品表的数字 ID;管理员生成授权码时使用。 |
| product | WINDOWS_APP / WEB_APP / ANDROID | 产品编码;客户端请求必须与所购买授权匹配。 |
| license_id / id | 4 | 某一条授权记录的数字 ID;管理员绑定、配置、续期、禁用时使用。生成授权响应 keys[].id 或授权列表可查看。 |
| license_key | AAAAAAAA-BBBBBBBB-CCCCCCCC-DDDDDDDD | 客户凭据;以上仅为无效格式示例。不是授权 ID。完整码只在生成时展示,客户端无需填写 license_id。 |
| account_id / device_id | customer-001 / deployment-01 | 绑定身份;应用应提供稳定设备 ID,供自助换绑复制使用。 |
配置页的 offline_grace_seconds:0=不允许断网缓存,3600=1小时,21600=6小时,86400=1天,最高604800=7天。只影响新签名响应的缓存授权,不延长许可证自身到期时间。收到明确停用/过期响应应立即拒绝,不回退缓存。
响应包含 server_time、offline_grace_seconds、offline_until。使用离线缓存之前必须重新验签并匹配产品、授权码摘要、账户、设备和当前时间;只在网络不可达时使用。策略变更在下一次联网验证后生效,已发出的离线响应不能远程撤回。运行中立即停用需要应用定时 heartbeat;建议60秒。旧安卓v47仍固定6小时;修改后源码在后续新包中支持可配置策略。
POST /api/license/activate
{"product":"WINDOWS_APP","license_key":"客户授权码",
"account_id":"customer-001","device_id":"machine-001",
"nonce":"32位随机小写十六进制","platform":"windows"}
验证签名仅使用 Base64 解码 signed_payload 的原始字节;算法 RSA-SHA256 / PKCS1 v1.5。只读取签名内部 ok、action、product、account_id、device_id、nonce、server_time、valid_until、license_key_hash 与配置;外层字段不能用于权限决定。nonce 每次随机,联网响应时校验时间差。check 不激活名额,不用于替代 verify 的设备授权。
Web/Node.js SDK(现代浏览器 WebCrypto、Node20+) · Windows/.NET8 SDK(无外部 NuGet) · 原有 Android Java 等 SDK
import {LicenseClient} from './LicenseClient.mjs';
const client = new LicenseClient({publicPem: PINNED_PEM,
product:'WEB_APP',licenseKey:process.env.LICENSE_KEY,
accountId:'customer-001',deviceId:'deployment-01'});
const license = await client.request('activate');
// 后续使用 verify/heartbeat;可从 license.app_config 读取签名配置。
// .NET8:将下载的 LicenseClient.cs 加入项目
var client = new LicenseClient("https://lis.pipbest.com", pinnedPem,
"WINDOWS_APP", licenseKey, "customer-001", stableDeviceId);
var result = await client.RequestAsync("activate");
两个新增 SDK 默认每次在线验签,未自动持久化缓存;离线策略的落盘存储与运行时功能控制由应用实现,避免不透明地允许离线运行。桌面应用应从安全配置读取授权码,Web 后端从环境变量读取,不在浏览器代码中公开管理 Token。设备 ID 不应每次启动随机。
管理员对客户独立授权开启 self_service_enabled,并设 rebind_cooldown_seconds。客户通过产品编码和完整授权码进入自助页,查看自身授权、激活新设备、解绑或换绑。不能延长有效期、改变设备容量、修改服务器配置、清除封禁。接口每来源IP每5分钟最多30次请求,修改操作记录日志并锁定授权记录防并发绕过名额。
授权码即自助账户凭据,不能在URL传递或公开分发。嵌入APK/浏览器公开分发的共用码默认关闭自助管理;否则拿到码的玩家也能管理该码设备。用户版与运营方共用配置码应分开生成。
POST /api/self/status {"product":"WINDOWS_APP","license_key":"客户授权码"}
POST /api/self/bind {"product":"WINDOWS_APP","license_key":"客户授权码",
"account_id":"customer-001","device_id":"new-machine","platform":"windows"}
POST /api/self/rebind {"product":"WINDOWS_APP","license_key":"客户授权码",
"binding_id":123,"account_id":"customer-001","device_id":"new-machine"}
POST /api/self/unbind {"product":"WINDOWS_APP","license_key":"客户授权码","binding_id":123}
客户端校验可以被专业逆向修改。商业核心功能和API应由服务端验证授权/短期票据。浏览器来源头、设备ID、客户端上报的证书均不是硬件身份。平台不会自动替其他 Web/Windows 工程接入权限限制,需要使用上述 SDK 在相应业务入口调用。