重要
License 授权的核心设计:服务端持有私钥签发 License 证书,业务服务随部署导入证书并使用内置公钥验签,从而实现离线、可审计、低侵入的授权控制。
环境说明
- 语言:Go
- 场景:私有化部署 / 内网部署 / 微服务授权
- 方式:非对称签名 + 服务启动校验 + 周期性校验
1.简介
私有化交付场景下,服务通常部署在客户内网,不能依赖公网授权中心实时校验。
因此 License 设计需要满足:
| 目标 | 说明 |
|---|---|
| 离线可用 | 客户环境无公网时仍可完成授权校验 |
| 不暴露私钥 | 私钥只在签发侧保存,不进入业务服务、不进入客户环境 |
| 部署简单 | License 文件跟随服务部署导入 |
| 可限制范围 | 支持有效期、模块、节点数、租户、环境等约束 |
| 可审计 | 授权内容可解析、可验签、可追溯 |
核心原则:签发权在服务端,校验权在业务服务;私钥不下发,公钥可内置。
2.整体设计
2.1 角色划分
| 角色 | 持有内容 | 职责 |
|---|---|---|
| License 签发服务 | 私钥 | 生成授权内容并签名 |
| 业务服务 | 公钥 | 导入 License 后验签并读取授权范围 |
| 部署系统 | License 文件 | 随服务部署分发授权文件 |
| 运维人员 | 授权申请信息 | 申请、替换、续期 License |
2.2 授权流程
授权申请信息
↓
License 签发服务
↓ 使用私钥签名
License 文件 / License 证书
↓ 随业务服务部署导入
业务服务启动
↓ 使用内置公钥验签
读取授权范围
↓
启用对应功能模块3.说明
3.1 License 文件内容
License 文件建议分为两部分:
| 部分 | 内容 | 是否敏感 |
|---|---|---|
| Payload | 授权主体、有效期、模块列表、部署规模等 | 否,但需要避免泄露客户信息 |
| Signature | 使用私钥对 Payload 签名后的结果 | 否,不能反推出私钥 |
示例结构如下:
| |
需要注意的是,subject、product、modules 在公开文章中必须脱敏。真实项目中可以使用客户编号、产品编码、模块编码,不建议直接写客户名称或内部服务名。
3.2 签发逻辑
签发服务只做两件事:
- 生成标准化 Payload;
- 使用私钥对 Payload 做签名。
伪代码如下:
| |
关键点:
| 点 | 说明 |
|---|---|
| Payload 必须规范化 | 避免 JSON 字段顺序、空格、编码差异导致验签失败 |
| 私钥必须独立保存 | 不进入镜像、不进入 Git、不进入客户环境 |
| 签发记录需要留痕 | 便于授权追踪、续期、吊销 |
3.3 服务侧校验逻辑
业务服务启动时读取 License 文件,使用内置公钥验签。
| |
建议校验点:
| 校验项 | 说明 |
|---|---|
| 签名校验 | 确认 License 未被篡改,且确实由私钥持有方签发 |
| 有效期 | 到期后拒绝启动或降级运行 |
| 模块权限 | 未授权模块不加载或不可调用 |
| 部署规模 | 校验节点数、实例数、租户数等限制 |
| 环境绑定 | 可选,绑定机器码、集群 ID、租户 ID 等 |
3.4 为什么不用对称加密
| 方案 | 优点 | 问题 |
|---|---|---|
| 对称密钥 | 实现简单 | 业务服务必须持有同一密钥,密钥泄露后可伪造 License |
| 非对称签名 | 私钥不下发,业务侧只需要公钥 | 实现略复杂,但安全边界清晰 |
License 授权推荐使用非对称签名。业务服务只负责验签,不具备签发能力。
3.5 私钥管理
私钥是整套 License 体系的根权限。
不建议:
- 私钥写入代码仓库;
- 私钥打进业务镜像;
- 私钥通过配置文件下发到客户环境;
- 所有环境共用同一把私钥且无轮换机制。
建议:
| 项 | 建议 |
|---|---|
| 存储 | 放在独立签发服务或 KMS/HSM 中 |
| 权限 | 只允许授权签发流程访问 |
| 审计 | 记录签发人、签发时间、授权范围 |
| 轮换 | 支持多公钥验签,平滑切换新旧密钥 |
3.6 部署集成
License 文件可以跟随服务部署导入,常见方式:
| 部署方式 | License 挂载方式 |
|---|---|
| 二进制部署 | 放在指定配置目录 |
| Docker | 通过 volume 挂载 |
| Kubernetes | 使用 Secret / ConfigMap 挂载 |
Kubernetes 示例:
| |
需要注意的是,License 本身不等同于私钥。License 可以随部署分发,私钥不能。
4.常见问题
4.1 License 被复制怎么办
如果只校验签名和有效期,License 文件可以被复制到其他环境使用。
解决方案:
| 方案 | 说明 |
|---|---|
| 绑定机器码 | 适合物理机或固定虚拟机部署 |
| 绑定集群 ID | 适合 Kubernetes 私有化部署 |
| 绑定租户 ID | 适合多租户平台 |
| 绑定节点规模 | 限制最大节点数或实例数 |
是否绑定环境,需要结合交付方式决定。绑定越强,运维复杂度越高。
4.2 到期后如何处理
常见处理方式:
| 策略 | 行为 | 适用场景 |
|---|---|---|
| 拒绝启动 | 服务启动失败 | 强授权控制 |
| 降级运行 | 核心功能可用,高级模块禁用 | 避免生产事故 |
| 只告警 | 不影响运行 | 试用期、灰度阶段 |
生产环境不建议到期后直接导致核心链路不可用,除非合同和交付流程明确允许。
4.3 如何支持续期
续期本质是重新签发一份新 License:
- 读取原授权主体;
- 调整
expiresAt或授权范围; - 使用私钥重新签名;
- 替换部署侧 License 文件;
- 服务重启或热加载。
如果需要热加载,需要监听 License 文件变化,并重新执行验签流程。
5.总结
License 微服务授权的核心不是加密,而是签名与验签的权限隔离。
| 设计点 | 结论 |
|---|---|
| 私钥 | 只在签发服务侧保存 |
| 公钥 | 内置到业务服务,用于验签 |
| License | 随部署导入,描述授权范围 |
| 校验 | 启动时校验,运行中可周期性校验 |
| 安全边界 | 业务服务只能验证,不能签发 |
一句话说明:License 签发服务使用私钥签发服务证书,业务服务随部署导入 License,并通过内置公钥验签授权范围。
6.参考
- RSA / ECDSA 非对称签名
- X.509 证书体系
- Kubernetes Secret 挂载配置
- 私有化部署授权设计