开发文档

鲜花交易系统与鲜花交易平台(PHP / ThinkPHP 版)的研发记录:功能上线、架构演进与实施经验,按发布日期持续更新。

私有化交付的软件授权怎么设计:授权码、心跳与吊销

私有化交付的固有矛盾

客户买了系统,部署在自己的服务器上。对厂商来说,这里有一个绕不开的问题:代码在别人机器上,怎么保证授权被遵守?

常见做法有三种:

  1. 纯源码交付,不做技术控制:靠合同与信誉。适合定制项目,不适合标准化产品。
  2. 代码加密(如 ionCube):防反编译,但客户运维会抵触,且升级麻烦。
  3. 授权码 + 运行时校验:代码可见,但关键能力(版本、期限、模块、租户数)由授权控制。

这套平台走第三条:授权控制能力,不控制代码可见性。

授权码里有什么

授权码是一段签名的凭证,内容大致包括:

  • 客户与项目标识;
  • 版本/套餐(trial / basic / advanced / flagship / 源码版);
  • 已购模块白名单;
  • 有效期(试用期或年费到期日);
  • 容量限制(如租户数、门店数)。

签名的作用是防篡改:客户改不了里面的期限,只能向厂商申请重签。

关键设计是授权码的真源在客户后台,不在配置文件。早期我们把 license key 写在 .env 里,结果换码要运维改文件重启;后来收敛到"后台自助激活 + 数据库存真源",运维不需要碰服务器。

实例绑定:防止一个授权码多机部署

授权码本身可以被复制。所以要绑定实例:客户首次激活时,把实例指纹(安装标识 + 服务器信息)登记到厂商侧,之后心跳上报时校验"这台机器是不是登记过的那台"。

这里有两个必须考虑的现实场景:

  • 换服务器:客户迁移机房,需要解绑旧实例、绑定新实例;
  • 同机重装:磁盘重装后实例标识可能变化,需要"重签换码 + 改绑"。

对应的产品动作是「重新签发(换码)」与「实例改绑」。这两个功能必须有,否则每次客户换机器都要厂商手工改数据库。

心跳与吊销

激活后,客户侧定时向厂商上报心跳:版本、实例标识、当前租户/用户规模、最近错误摘要。

心跳有三个用途:

  1. 续期与到期提醒:到期前按剩余天数在后台提示,而不是某天早上突然不能用;
  2. 版本统计:厂商知道客户在跑哪个版本,发版通知才有针对性;
  3. 吊销下发:授权被吊销(欠费、违约)时,通过吊销列表(CRL)下发到客户侧,客户侧在下一次心跳或启动时读取生效。

CRL 的设计要点是用稳定的唯一标识做键。我们踩过一次坑:吊销时写入的字段与校验时读取的字段不是同一个 ID(一个用授权码、一个用实例号),导致"已吊销但系统照常运行"。修复后统一为授权码,并加了一条自检:吊销一条后立刻在客户侧验证效果。

受限模式:不能用也不能白跑

授权过期或未激活时,系统不能直接 500,也不能毫无限制。做法是受限模式:

  • 允许登录、允许查看已有数据;
  • 禁止写入与新增(下单、发布、结算);
  • 后台顶部显示醒目状态条与到期提示;
  • 菜单按白名单裁剪,只保留与授权相关的页面。

这样客户不会丢数据,也不会误解为"系统坏了",同时形成续费的合理压力。

一段经验

授权体系最容易出事的地方不是加密强度,而是状态同步:厂商侧改了授权,客户侧不知道;客户换了机器,厂商侧还绑着旧实例。

所以整套设计的重点放在可解释的状态:后台能明确显示"当前授权从哪来、什么时候到期、实例什么时候登记、有没有被吊销"。客户和客服看同一份信息,纠纷就少一半。

本文属于「开发文档」系列,记录鲜花交易系统(PHP + ThinkPHP 8 + MySQL 8)的实际研发进展。想了解功能清单与报价,可前往系统报价或联系我们。