一、系统简介
PHP多产品通用授权控制系统,用于售卖PHP网站程序时的授权管理。核心功能:
- 多产品支持:一套系统管理多款售卖程序
- 授权包管理:每个客户生成唯一授权码,退款一键禁用
- 授权注入工具:上传源码包自动注入SDK、修改校验码、埋入探针,一键打包下载
- 远程授权模式(新增):不新增任何文件,所有授权代码注入到目标程序已有文件中,授权逻辑完全在控制端,实时禁用,维护方便,更安全更隐蔽
- 注入策略选择器:根据程序特性自动选择6种注入方案(保守型/均衡型/严格型/API专用型/后台专用型/核心文件型),智能适配各种程序结构
- 程序特性自动检测:自动检测30+种程序特性(自动加载、前后端分离、CLI脚本、控制器类、中间件、服务容器、模板引擎、数据库ORM、缓存系统、队列系统、认证系统、后台管理面板、REST API、事件系统、日志系统、多语言支持、插件系统等)
- 案例库:记录历史遇到的问题和解决方案,辅助智能判断,避免类似问题再次发生
- 注入后验证:6项自动检查(SDK完整性、注入文件语法、安装文件保护、独立监控验证、探针多样性、运行时探针CLI模式检测),确保注入质量
- 注入配置(高级):可视化修改文件识别规则和伪装名称,适配不同结构的PHP程序
- 程序管理:预存未注入程序,注入时可直接选择,无需每次上传
- 前端构建目录检测:自动识别前端构建目录,确保SDK不被前端构建覆盖
- 注入记录:历史注入记录管理,支持重新下载、查看注入文件明细
- 多设备部署:同一授权包允许多台服务器部署,可限制数量
- 设备指纹管理:通过设备指纹对单个设备进行管理操作,避免因为一个设备的原因需要全部禁用
- 无感校验:客户程序后台静默校验,用户完全无感知
- 2FA两步验证:管理员登录支持Google Authenticator动态验证码
- 企微通知:登录成功/失败实时推送到企业微信群
- 代码混淆加密:注入时可选择混淆加密代码,避免被看出来或修改配置
- 盗版检测:注入的代码被修改或删除即判定为盗版,恢复完整代码则判断为正常授权
- SDK异常检测:SDK文件夹被删除或修改即判定为SDK异常,自动上报并锁定
- 离线授权检测:超过48小时没有上报的即判定为离线,恢复上报后判定为正常授权
- 独立监控代码:随机注入到文件中,监控SDK文件夹和里面代码的完整性,出现被修改等操作自动上报控制端并锁定
- 探针互相校验:删除一个探针立即锁定,多入口探针互相校验
- 运行时探针CLI模式检测:CLI模式下跳过运行时探针检查,避免破坏进程守护/后台任务
- 防破解:多入口探针、AES加密缓存、完整性校验、运行时常量、每个文件探针代码独立随机
二、部署安装
2.1 环境要求
- PHP >= 7.4(推荐 8.0+)
- MySQL >= 5.7(推荐 8.0)
- PHP扩展:PDO、pdo_mysql、openssl、curl(推荐)
- Web服务器:Nginx 或 Apache
2.2 部署步骤
- 创建数据库:新建数据库,编码选择 utf8mb4
- 导入数据表:将
auth_server/db.sql 导入数据库
- 修改配置:编辑
auth_server/config.php,填写数据库连接信息
- 上传文件:将
auth_server 目录上传到服务器,绑定域名
- 配置Web服务器:参考项目中的
nginx.conf 配置Nginx
💡 宝塔面板用户:直接在宝塔添加站点,根目录指向 auth_server,PHP版本选择7.4以上,在配置文件中禁止访问 lib 和 config 目录即可。
2.3 已部署用户升级(v1.0 → v1.1)
如果已经部署了v1.0版本,执行以下操作升级:
- 备份数据库和现有文件
- 在数据库中执行
upgrade_v1.1.sql 升级脚本
- 上传新的文件覆盖旧文件(config.php 除外,保留你的数据库配置)
- 刷新页面即可使用2FA和Webhook新功能
三、登录系统
3.1 默认账号
⚠️ 首次登录后请立即修改密码!默认密码存在安全风险。
3.2 登录安全机制
- CSRF防护:所有表单提交携带令牌验证
- 失败锁定:连续5次密码错误,账户锁定15分钟
- Session安全:HttpOnly、SameSite=Strict、防固定攻击
- 登录成功:重新生成Session ID
3.3 修改密码
登录后,点击左侧菜单「修改密码」,输入原密码和新密码即可。新密码至少8位。
四、两步验证 (2FA)
4.1 什么是2FA
两步验证(Two-Factor Authentication)是在密码之外增加的第二重身份验证。启用后,登录时需要:
- 输入用户名和密码(第一步)
- 输入身份验证器APP中的6位动态验证码(第二步)
即使密码泄露,没有你的手机也无法登录,大幅提升账户安全性。
4.2 支持的身份验证器
- Google Authenticator(谷歌验证器)
- Microsoft Authenticator(微软验证器)
- Authy
- 1Password
- 其他支持TOTP协议的验证器
4.3 启用2FA步骤
- 登录后台,点击左侧菜单「安全设置」
- 找到「两步验证」区域,点击「开始绑定2FA」
- 用手机上的身份验证器APP扫描页面上的二维码
- (无法扫描时)手动输入页面显示的密钥
- 验证器APP会显示6位动态验证码,输入到页面输入框
- 点击「确认启用2FA」,绑定成功
⚠️ 绑定成功后,请务必保存好密钥和恢复码。如果手机丢失,将无法登录!建议同时在多个设备上绑定。
4.4 关闭2FA
在「安全设置」页面,输入登录密码后点击「关闭2FA」即可。
4.5 验证码错误怎么办
- 检查手机时间是否准确(TOTP依赖时间同步)
- 确认输入的是当前最新的6位验证码(每30秒刷新一次)
- 连续5次错误会退回第一步重新登录
五、多渠道通知系统(推荐)
5.1 功能说明
多渠道通知系统是对原有企业微信Webhook通知的全面升级,支持多种推送渠道、多个Webhook地址、按事件类型订阅,让你第一时间掌握授权系统的所有动态。
支持的推送渠道:
- ✅ 企业微信群机器人
- ✅ 钉钉群机器人(支持加签)
- ✅ 飞书群机器人(支持加签)
- ✅ 自定义Webhook(任意HTTP接口)
支持的15种事件类型:
| 分类 | 事件类型 | 触发时机 |
| 系统登录 | 管理员登录成功 | 后台管理员登录成功时 |
| 管理员登录失败 | 后台管理员登录失败时 |
| 2FA验证失败 | 二次验证失败时 |
| 授权包 | 授权包禁用 | 授权包被禁用时 |
| 授权包启用 | 授权包被启用时 |
| 授权包删除 | 授权包被删除时 |
| 设备 | 新设备上报 | 新设备首次上报授权时 |
| 设备禁用 | 设备被禁用时 |
| 设备启用 | 设备被启用时 |
| 异常检测 | SDK异常 | SDK文件被修改或删除时 |
| 授权异常 | 签名验证失败、授权包不存在时 |
| 盗版检测 | 注入代码被修改或删除时 |
| 注入操作 | 注入成功 | 授权注入成功时 |
| 注入失败 | 授权注入失败时 |
5.2 核心特性
- 多Webhook管理:可以添加多个Webhook地址,每个地址独立配置订阅的事件
- 事件订阅:每个Webhook可以独立勾选接收哪些事件,同一事件可以推送到多个Webhook
- 安全加密:Webhook地址加密存储,域名白名单验证,防SSRF攻击
- 可靠推送:失败自动重试(最多2次),10秒超时,完整推送日志记录
- 连接测试:每个Webhook支持一键测试,验证地址是否可用
- 向后兼容:保留原有的企业微信Webhook通知,两套系统并行运行
5.3 添加Webhook
- 登录后台,点击左侧菜单「通知设置」
- 点击右上角「+ 添加Webhook」按钮
- 填写名称(如"企微告警群"、"钉钉运维群")
- 选择渠道(企业微信/钉钉/飞书/自定义)
- 粘贴Webhook地址
- 如果是钉钉或飞书,且开启了加签,填写签名密钥(可选)
- 勾选需要订阅的事件(默认全部勾选)
- 点击「添加」按钮
- 添加成功后,点击「测试」按钮,验证Webhook是否可用
5.4 获取各渠道Webhook地址
企业微信:
- 打开企业微信,进入要接收通知的群聊
- 点击右上角「...」→「群机器人」→「添加机器人」
- 给机器人起个名字,点击「添加」
- 复制机器人的Webhook地址
钉钉:
- 打开钉钉,进入要接收通知的群聊
- 点击右上角「...」→「智能群助手」→「添加机器人」
- 选择「自定义」机器人
- 给机器人起个名字,选择安全设置(建议使用加签)
- 点击「完成」,复制Webhook地址和加签密钥
飞书:
- 打开飞书,进入要接收通知的群聊
- 点击右上角「设置」→「群机器人」→「添加机器人」
- 选择「自定义机器人」
- 给机器人起个名字,选择安全设置(建议使用签名校验)
- 点击「添加」,复制Webhook地址和签名密钥
5.5 管理Webhook
- 编辑:点击「编辑」按钮,可以修改名称、地址、密钥、订阅事件
- 测试:点击「测试」按钮,发送测试消息,验证Webhook是否可用
- 启用/禁用:点击「禁用」或「启用」按钮,临时开启或关闭该Webhook的推送
- 删除:点击「删除」按钮,永久删除该Webhook(不可恢复)
5.6 查看推送日志
在通知设置页面下方,可以查看所有推送日志,支持按Webhook、事件类型、状态筛选。
- 每条日志包含:Webhook名称、事件类型、推送状态、错误信息、推送时间
- 成功的日志显示绿色"成功"标签,失败的显示红色"失败"标签
- 如果推送失败,可以查看错误信息,排查原因
5.7 安全机制
- 地址加密:Webhook地址使用XOR加密存储,即使数据库泄露也无法直接获取明文地址
- 域名白名单:企业微信、钉钉、飞书渠道必须使用官方域名,防止推送到恶意地址
- 防SSRF:禁止推送到内网IP地址(10.x、172.16.x、192.168.x、127.x),防止服务器端请求伪造攻击
- 加签支持:钉钉和飞书支持加签验证,提高Webhook地址的安全性
- 失败重试:推送失败自动重试2次,间隔0.5秒,提高推送成功率
- 超时控制:10秒请求超时,5秒连接超时,防止长时间阻塞
5.8 常见问题
Q1: 收不到推送通知怎么办?
A: 请按以下步骤排查:1)点击「测试」按钮,确认Webhook地址是否可用;2)检查Webhook是否已启用;3)检查是否勾选了对应的事件类型;4)查看推送日志,确认是否有失败记录及错误信息;5)检查服务器是否能访问外网(企微/钉钉/飞书API地址)。
Q2: 可以同时推送到多个群吗?
A: 可以。添加多个Webhook地址,每个地址对应一个群,然后为每个Webhook勾选相同的事件类型即可。同一事件会同时推送到所有订阅了该事件的Webhook。
Q3: 不同事件推送到不同群可以吗?
A: 可以。比如创建"安全告警群"只订阅登录失败、SDK异常、盗版检测等安全事件,创建"业务通知群"只订阅新设备上报、注入成功等业务事件。每个Webhook独立配置订阅的事件类型。
Q4: 原有的企业微信Webhook通知还能用吗?
A: 可以。多渠道通知系统与原有的企业微信Webhook通知是并行运行的,两套系统互不影响。建议迁移到新的多渠道通知系统,功能更强大。
Q5: 推送会影响系统性能吗?
A: 不会。推送操作是同步执行的,但有10秒超时控制,不会长时间阻塞。对于登录、注入等操作,推送在主要逻辑完成后执行,不影响核心功能。建议不要配置过多Webhook(一般2-3个足够),避免推送时间过长。
✅ 多渠道通知系统让你随时随地掌握授权系统的所有动态,异常情况第一时间通知,安全事件及时处理,是保障授权系统安全运行的重要工具!
六、产品管理
6.1 什么是产品
产品对应你售卖的每一款程序。比如你有3款程序在卖(商城系统、CRM系统、CMS系统),就创建3个产品。
6.2 添加产品
- 点击左侧菜单「产品管理」
- 点击「+ 添加产品」
- 填写产品标识(英文唯一,如
shop_v1)
- 填写产品名称(如"商城系统V1")
- 设置默认最大部署设备数(每个授权包默认允许几台服务器使用)
- 选择状态(启用/禁用)
- 点击「确认添加」
💡 产品标识一旦创建不可修改,用于SDK中标识产品归属。A产品的授权码不能在B产品上使用。
6.3 编辑/删除产品
- 编辑:可以修改产品名称、默认设备数、状态,产品标识不可修改
- 删除:如果产品下存在授权包,无法删除,需先删除关联的授权包
七、程序管理(预存未注入程序)
7.1 功能说明
程序管理允许你预存未注入的程序源码,在授权注入工具中可以直接选择程序管理中的程序,无需每次都上传。适合经常需要注入的程序,可以节省上传时间,提高效率。
💡 程序管理中存储的是未注入的原始程序,注入时会从程序管理中复制一份进行注入,不会修改原始程序。可以随时更新程序管理中的程序版本。
7.2 上传程序
- 点击左侧菜单「程序管理」
- 点击「+ 上传程序」
- 填写程序名称(如"商城系统V1.2")
- 填写程序版本(如"v1.2.0")
- 选择程序文件(ZIP格式,最大支持100MB)
- 填写备注(可选,用于记录程序的特殊说明)
- 点击「确认上传」
7.3 管理程序
- 查看程序列表:显示所有预存的程序,包括程序名称、版本、文件大小、上传时间、备注等信息
- 更新程序:可以重新上传程序文件,更新到新版本,旧版本会被覆盖
- 编辑程序信息:可以修改程序名称、版本、备注等信息
- 删除程序:删除不需要的程序,删除后无法恢复
- 下载程序:可以下载预存的原始程序文件
7.4 在注入工具中使用
- 点击左侧菜单「授权注入工具」
- 在「程序来源」中选择「从程序管理选择」
- 在下拉列表中选择需要注入的程序
- 选择产品、授权包、填写校验码等信息
- 点击「开始注入」按钮
- 等待注入完成,下载注入后的源码包
✅ 使用程序管理的优势:1)无需每次上传,节省时间;2)原始程序统一管理,版本清晰;3)注入时从程序管理复制,不会修改原始程序;4)可以随时更新程序版本。
7.5 注意事项
- 程序管理中存储的是未注入的原始程序,不要上传已经注入过的程序
- 程序文件必须是ZIP格式,最大支持100MB
- 更新程序时,旧版本会被覆盖,建议先备份旧版本
- 删除程序后无法恢复,请谨慎操作
- 程序管理中的程序可以被多次注入,每次注入都会生成新的注入记录
八、授权包管理(核心功能)
7.1 什么是授权包
每卖出一份程序,生成一个授权包(PKG_CODE)。这个授权码会预埋到客户拿到的源码中,作为该客户的唯一身份标识。
7.2 生成授权包
- 点击左侧菜单「授权包管理」
- 点击「+ 生成授权包」
- 选择产品(这款程序属于哪个产品)
- 填写订单号(对应你的销售订单,方便查找)
- 填写客户姓名、联系方式(可选,方便售后)
- 设置最大设备数(0=使用产品默认值,也可单独设置)
- 填写备注(可选)
- 点击「生成授权包」
生成后会得到一个唯一的 PKG_CODE,如 PKG20260830123456789。
7.3 授权包状态
| 状态 | 说明 |
| 正常 | 授权有效,客户程序正常运行 |
| 已禁用 | 授权被禁用(通常是退款),客户程序会被锁定 |
7.4 查看授权包下的设备
点击授权包操作列的「设备」按钮,可以查看该授权码被部署到了哪些服务器,包括:
- 设备指纹(唯一标识一台服务器)
- 部署域名
- 服务器IP
- 首次上报时间、最后上报时间
7.5 编辑授权包
点击「编辑」可以修改订单号、客户信息、最大设备数、备注。PKG_CODE和产品不可修改。
九、授权注入工具(推荐)
✅ 推荐使用自动注入工具:上传源码压缩包,系统自动完成SDK注入、校验码修改、探针埋入,无需手动操作,省时省力且不易出错。
8.1 功能说明
授权注入工具可以自动完成以下所有操作:
- 解压ZIP源码包,自动识别源码根目录
- 复制 client_sdk SDK目录到源码根目录
- 自动修改校验码:将选择的授权包PKG_CODE写入SDK配置
- 自动写入产品标识、授权服务器URL
- 自动创建runtime缓存目录和.htaccess保护
- 自动扫描所有PHP文件,智能识别文件类型并埋入对应探针
- 自动跳过已有授权代码的文件,避免重复注入
- 重新打包为ZIP,提供下载
8.2 使用步骤
- 登录后台,点击左侧菜单「授权注入工具」
- 点击上传区域,选择你的源码压缩包(ZIP格式,最大100MB)
- 下拉选择对应的授权包(系统自动获取PKG_CODE)
- 点击「开始自动注入」按钮
- 等待处理完成(页面显示进度条和当前步骤)
- 查看注入结果和注入文件明细
- 点击「下载注入后的源码包」,直接发给客户
8.3 自动埋入的三种探针
| 探针类型 | 自动注入目标文件 | 作用 |
| 加载探针 |
index.php、admin.php、api.php、install.php等入口文件;admin/、api/目录下的文件 |
文件被访问时自动加载SDK并触发授权校验 |
| 运行时探针 |
common.php、function.php、config.php、Base控制器、Base模型、Service、Middleware等公共文件 |
轻量校验运行时常量,代码极短,难以全部清理 |
| CLI探针 |
文件名或目录包含cli、cron、task、script、command的PHP文件 |
防止命令行脚本绕过网页授权直接操作数据库 |
8.4 注入结果页面
注入完成后,结果页面展示:
- 注入统计:扫描PHP文件数、各类型探针注入数量、跳过文件数
- 注入文件明细:详细表格展示每个注入的文件路径和探针类型
- 注入日志:每一步的处理记录
- 下载按钮:一键下载处理后的源码包
💡 建议注入后抽查几个关键入口文件,确认探针已正确埋入。不同项目结构不同,自动注入覆盖了绝大多数常见情况,特殊项目可能需要手动补充个别探针。
8.5 处理时间参考
| 源码包大小 | 预计耗时 |
| < 5MB | 2-5秒 |
| 5-30MB | 10-30秒 |
| 30-100MB | 30-90秒 |
主要耗时在解压ZIP和重新打包ZIP,探针注入本身很快。处理期间请勿关闭或刷新页面。
十、远程SDK授权模式(更安全,推荐)
10.1 什么是远程SDK授权模式
远程授权模式是一种全新的授权注入方式,与传统的本地SDK模式不同:
- 不新增任何文件:所有授权代码都注入到目标程序已有的文件中,不生成SDK文件夹,用户对比源码无法发现新增文件
- 授权逻辑在控制端:目标程序中只有远程调用代码(约200行),完整的授权验证逻辑完全在控制端服务器,用户无法通过反编译获取授权逻辑
- 实时禁用:控制端禁用授权后,目标程序在请求间隔到期后(默认60秒)立即生效,不需要等待本地缓存过期
- 维护方便:授权逻辑更新只需修改控制端代码,所有已发货的程序立即生效,不需要重新注入发货
- 后台静默执行:远程授权请求使用异步非阻塞方式(fsockopen + register_shutdown_function),用户完全无感知,不影响页面加载速度
💡 推荐场景:对安全性要求高、需要实时禁用、经常需要更新授权逻辑的场景。传统本地SDK模式仍然保留,适合对可用性要求极高、控制端可能长时间不可用的场景。
10.2 与本地SDK模式对比
| 对比项 | 本地SDK模式(传统) | 远程授权模式(推荐) |
| 新增文件 | 1个SDK文件夹(2-3个文件) | 0个文件,所有代码注入到已有文件 |
| 目标程序注入代码量 | 约1600行(含SDK完整逻辑) | 约300行(远程调用+探针+监控) |
| 授权逻辑位置 | 目标程序中(可被反编译) | 控制端(无法获取) |
| secret_key安全性 | 目标程序中(可被反编译) | 只在控制端,目标程序只有verify_key |
| 禁用生效时间 | 需等缓存过期(最长4小时) | 请求间隔到期后立即生效(默认60秒) |
| 控制端宕机影响 | 无(本地缓存可离线使用) | 缓存机会用完后锁定(默认1次机会) |
| SDK更新维护 | 需重新注入发货 | 控制端更新即生效 |
| 隐藏性 | ⭐⭐⭐(SDK文件夹可见) | ⭐⭐⭐⭐⭐(无新增文件) |
| 整体安全性 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
10.3 使用方法
在「授权注入工具」页面的「授权模式」选项中选择「远程授权模式」,然后配置以下参数:
- 请求间隔(秒):默认60秒。控制端请求间隔,间隔越长控制端压力越小,禁用生效越慢。建议设置为30-300秒。
- 缓存机会次数:默认1次。控制端连接失败时可使用缓存的次数,0表示连接失败立即锁定。建议设置为1-3次,平衡安全性和可用性。
- 混淆级别:默认L1(基础混淆)。
- L0 - 不混淆:原始代码,便于调试
- L1 - 基础混淆(推荐):移除注释和空行,变量名随机化,确保100%不影响程序运行
- L2 - 进阶混淆:L1 + 字符串加密(API URL、授权码等关键字符串加密)
- L3 - 高级混淆:L2 + 代码压缩(合并短行,进一步减小代码体积)
⚠️ 注意:远程授权模式需要目标程序的服务器能够访问控制端域名(HTTPS)。如果目标程序的服务器无法访问外网,或控制端域名可能变更,请使用本地SDK模式。
10.4 工作原理
远程授权模式的工作流程如下:
- 代码注入:注入器自动识别目标程序的公共引导文件(如common.php、bootstrap.php),将远程授权核心代码(约200行)注入到该文件开头;同时在入口文件注入轻量探针,在配置文件注入独立监控代码。
- 首次访问:用户访问目标程序时,远程授权代码自动执行,异步发起HTTP请求到控制端的remote_auth.php接口,传递授权码、设备指纹、域名等信息。
- 异步执行:请求使用fsockopen非阻塞方式发出,页面立即开始渲染,用户完全无感知。页面渲染完成后(register_shutdown_function),才读取控制端的响应。
- 缓存管理:控制端返回授权状态后,结果加密存储到系统临时目录(sys_get_temp_dir),文件名随机,内容XOR加密。下次访问时,如果未到请求间隔,直接使用缓存。
- 缓存失败降级:如果系统临时目录不可写(缓存失败),自动降级为每次请求都连接控制端,不锁定程序,确保可用性。
- 连接失败处理:如果控制端连接失败,使用缓存机会(默认1次)。缓存机会用完后,如果仍然连接失败,程序锁定,显示维护页面。
- 连接恢复:控制端恢复连接后,自动解锁,缓存机会刷新,程序恢复正常使用。
- 独立监控:配置文件中的独立监控代码会校验公共引导文件中的授权核心代码是否被删除或修改,如果发现异常,立即上报控制端并锁定程序。
10.5 缓存机会机制详解
缓存机会是远程授权模式的核心容错机制,平衡安全性和可用性:
- 缓存机会不叠加:每次连接成功后,缓存机会刷新为设置的次数(默认1次),不会累计增加。
- 缓存机会只在连接失败时消耗:未到请求间隔时,直接使用缓存,不消耗缓存机会。
- 缓存机会为0且连接失败时锁定:确保控制端长时间不可用时,程序会被锁定,防止用户无限期离线使用。
时间线示例(请求间隔=60秒,缓存机会=1次):
| 时间 | 事件 | 缓存机会 | 程序状态 |
| 00:00 | 连接成功 | 1(刷新) | 正常 |
| 00:30 | 未到间隔,使用缓存 | 1(不消耗) | 正常 |
| 01:00 | 到间隔,连接失败 | 1→0(消耗) | 正常(使用缓存) |
| 01:30 | 未到间隔,使用缓存 | 0(不消耗) | 正常 |
| 02:00 | 到间隔,连接失败 | 0 | 锁定! |
| 02:30 | 已锁定 | 0 | 维护页面 |
| 03:00 | 到间隔,连接成功 | 1(刷新) | 恢复正常 |
10.6 响应签名验证
为了防止控制端响应被篡改或伪造,远程授权模式使用HMAC-SHA256响应签名验证:
- 双密钥机制:每个授权包有两个密钥:
- secret_key:请求签名密钥,只在控制端,目标程序中不存在,用于验证目标程序的请求是否合法。
- verify_key:响应签名密钥,下发到目标程序,用于验证控制端的响应是否被篡改。
- 签名计算:控制端对响应数据(auth_status、msg、timestamp、nonce等)按键名排序后,使用verify_key计算HMAC-SHA256签名,随响应一起返回。
- 签名验证:目标程序收到响应后,使用相同的算法和verify_key重新计算签名,与响应中的签名对比,如果不一致则认为响应被篡改,视为连接失败。
10.7 设备指纹
远程授权模式使用与本地SDK模式相同的设备指纹算法,基于以下信息生成唯一的设备指纹(SHA-256):
- 服务器IP(SERVER_ADDR)
- 程序安装目录(__DIR__)
- 域名(HTTP_HOST)
- PHP版本(PHP_VERSION)
- 操作系统(PHP_OS)
同一授权包下的不同设备通过设备指纹区分,支持单设备禁用(不需要禁用整个授权包)。
10.8 注意事项
- 控制端域名变更:远程授权模式的控制端域名是注入时动态获取的,写入到目标程序的代码中。如果以后更换控制端域名,已发货的程序需要重新注入。建议控制端域名保持稳定。
- HTTPS要求:建议控制端使用HTTPS,确保远程授权请求的传输安全。如果使用HTTP,请求可能被中间人攻击截获或篡改。
- 控制端性能:远程授权模式下,每个目标程序每隔设置的间隔(默认60秒)就会请求一次控制端。如果有大量授权用户,控制端需要有足够的性能承载。建议控制端使用Redis缓存、数据库索引优化等手段提升性能。
- 防火墙设置:目标程序的服务器需要能够访问控制端的443端口(HTTPS)。如果目标程序的服务器有防火墙限制,请确保放行控制端域名。
- CLI模式:远程授权代码会自动检测CLI模式(定时任务、队列等),在CLI模式下跳过授权检查,不影响目标程序的后台任务运行。
10.9 常见问题
Q: 远程授权模式和本地SDK模式可以同时使用吗?
A: 不可以。一次注入只能选择一种模式。如果需要切换模式,需要重新注入。
Q: 控制端宕机后,已授权的程序会怎样?
A: 根据缓存机会设置,默认1次缓存机会。控制端宕机后,第一次连接失败使用缓存(程序正常),第二次连接失败程序锁定。控制端恢复后自动解锁。
Q: 用户删除了注入的授权代码会怎样?
A: 配置文件中的独立监控代码会检测到公共引导文件中的授权核心代码被删除,立即上报控制端并锁定程序。同时,入口文件的轻量探针也会检测授权代码是否存在。
Q: 远程授权模式支持前后端分离的程序吗?
A: 支持。注入器会自动识别前后端分离程序的结构,将授权代码注入到PHP后端的公共引导文件中,不会影响前端构建。前端构建时不会覆盖PHP后端文件。
Q: 如何验证远程授权模式是否正常工作?
A: 1)注入后访问目标程序,确认程序正常运行;2)在控制端「接口日志」页面查看是否有remote_auth的请求记录;3)在控制端禁用该授权包,等待请求间隔(默认60秒)后,刷新目标程序,确认显示维护页面。
十一、注入策略选择器(智能)
9.1 功能说明
注入策略选择器会根据程序的特性自动选择最合适的注入方案,无需手动配置。注入时会自动检测30+种程序特性,并根据检测结果选择6种注入方案之一。
提示:注入策略选择器是自动运行的,无需手动操作。注入日志中会显示选择的注入方案和选择原因,方便你了解注入器的决策过程。
9.2 六种注入方案
| 方案 | 名称 | 注入范围 | 适用场景 |
| A | 保守型(推荐) | 只在入口文件注入运行时探针 | 有自动加载机制、前后端分离、API服务、有CLI脚本的程序 |
| B | 均衡型 | 入口文件+控制器类注入运行时探针 | 传统MVC程序、没有自动加载机制的程序 |
| C | 严格型 | 所有PHP文件都注入运行时探针 | 简单程序、单文件程序、没有自动加载机制的程序 |
| D | API专用型 | 只在API入口文件和API控制器中注入 | 纯API服务、前后端分离的后端、微服务、RESTful API |
| E | 后台专用型 | 只在后台入口文件和后台控制器中注入 | 有后台管理面板的程序、CMS系统、企业管理系统 |
| F | 核心文件型 | 只在核心文件(入口、配置、核心类、基类)中注入 | 大型程序、复杂程序、框架程序、需要最小化性能影响的程序 |
9.3 程序特性自动检测
注入器会自动检测以下程序特性,用于选择注入方案:
- 基础特性:自动加载机制、命名空间、控制器类、模型类、CLI脚本、入口文件数量、总PHP文件数、框架类型
- 架构特性:前后端分离、前端构建、REST API、API路由、API控制器、后台控制器、后台管理面板
- 框架特性:中间件、服务容器、事件系统、日志系统、模板引擎、数据库ORM、缓存系统、队列系统
- 功能特性:认证系统、多语言支持、插件系统、核心类、配置文件、基类、Composer依赖
9.4 自动选择逻辑
注入器根据以下规则自动选择注入方案(优先级从高到低):
- 纯API服务(有REST API、有API控制器、没有模板引擎、没有后台管理面板)→ 方案D(API专用型)
- 有后台管理面板且没有前台(有后台控制器、有后台目录、没有模板引擎)→ 方案E(后台专用型)
- 大型复杂程序(PHP文件超过50个、有核心类、有服务容器、有事件系统)→ 方案F(核心文件型)
- 有自动加载机制 → 方案A(保守型)
- 前后端分离 → 方案A(保守型)
- 有CLI脚本/进程守护 → 方案A(保守型)
- 有控制器类且有命名空间 → 方案B(均衡型)
- 简单程序(PHP文件少于10个,没有自动加载,没有控制器类)→ 方案C(严格型)
- 默认 → 方案A(保守型)
9.5 查看注入策略选择结果
注入完成后,可以在注入日志中查看注入策略选择结果:
- 登录后台,点击左侧菜单「注入记录」
- 点击对应注入记录的「查看明细」
- 在注入日志中可以看到「【注入策略】自动选择方案X」以及选择原因
- 也可以在注入文件明细中查看每个文件注入的探针类型
9.6 运行时探针CLI模式检测
所有注入方案的运行时探针都包含CLI模式检测,在CLI模式下(`php_sapi_name() === 'cli'`)会跳过运行时探针检查,避免破坏进程守护/后台任务。
✅ 已解决的问题:之前注入后会破坏进程守护功能(如scheduler.php),原因是运行时探针在CLI模式下执行并退出。现在运行时探针增加了CLI模式检测,CLI模式下跳过检查,进程守护功能可以正常运行。
9.7 注入后验证
注入完成后,注入器会自动执行6项验证检查,确保注入质量:
- SDK完整性检查:SDK目录和文件是否存在,语法是否正确,类定义是否完整
- 注入文件语法检查:所有注入文件的语法是否正确,路径引用是否正确
- 安装文件保护检查:安装文件(install.php、setup.php等)没有被注入运行时探针
- 独立监控验证:独立监控代码至少注入2个文件
- 探针多样性检查:每个文件的探针代码都不一样(防止批量搜索删除)
- 运行时探针CLI模式检测检查:运行时探针包含CLI模式检测
验证结果会记录在注入日志中,如果发现问题会显示警告或错误信息。
十二、注入配置(高级功能)
9.1 功能说明
注入配置页面允许你可视化修改注入器的各项识别规则和伪装名称,适配不同结构的PHP程序。左侧菜单点击「注入配置」进入。
提示:配置保存后,下次注入时生效。已注入的程序不受影响。如果不确定如何配置,请保持默认值。
9.2 文件识别配置
控制注入器如何识别不同类型的PHP文件,决定使用哪种探针:
- CLI脚本文件名/目录名:匹配这些关键词的文件会被识别为命令行脚本,使用CLI探针(不输出HTML,只记录日志)
- 入口文件名:匹配这些文件名的文件会被识别为入口文件,使用加载探针(首次加载时执行授权检查)
- 运行时探针文件名:匹配这些文件名的文件会被识别为公共函数/配置文件,使用运行时探针(每次请求都检查授权状态)
- 基类/核心类文件名/目录名:匹配这些关键词的文件会被识别为基类文件,使用运行时探针
- 加载探针目录名:这些目录下的文件可能是入口文件,会进一步检查内容特征
9.3 入口文件内容特征配置
通过文件内容特征进一步判断是否为真正的入口文件,避免误判:
- 无namespace声明:入口文件通常不包含namespace声明,勾选后会排除有namespace的文件
- 有require/include:入口文件通常包含加载其他文件的语句,勾选后会优先识别有这些语句的文件
- 最少PHP行数:少于此行数的文件不识别为入口文件,避免注入到短小的配置文件中
9.4 前端构建目录检测
注入器会自动检测项目中的前端构建目录,确保SDK不放在这些目录下,避免前端构建时被覆盖。
检测依据(多重判断):
- 目录名匹配配置中的前端构建目录列表(如
web/dist、public、dist、build 等)
- 有
index.html 但没有 index.php,且有 .js/.css 文件
- 有
assets/、static/、js/、css/ 等静态资源目录,且PHP文件少于2个
前后端分离程序:如果目标程序是前后端分离的,注入器会自动识别前端构建目录,SDK会放在PHP后端目录,不会被前端构建覆盖。
9.5 伪装名称配置
控制注入器随机生成的目录名、文件名、常量名、函数名等,伪装成项目中常见的名称,避免被破解者针对性搜索删除:
- 缓存目录名/文件名:SDK内部缓存目录和文件的随机名称池
- 状态常量名:授权状态常量的随机名称池(如 GLOBAL_STATUS、SYSTEM_STATUS)
- 运行标记常量名:运行标记常量的随机名称池(如 GLOBAL_INIT、SYSTEM_INIT)
- 安全标记常量名:安全标记常量的随机名称池(如 AUTH_SDK_SAFE、SYSTEM_SAFE)
- 包校验码常量名:校验码常量的随机名称池(如 PKG_CODE、LOAD_CODE)
- 产品标识常量名:产品标识常量的随机名称池(如 PRODUCT_KEY、APP_KEY)
- 授权服务器URL常量名:服务器URL常量的随机名称池(如 AUTH_SERVER_URL、API_SERVER_URL)
- 锁定函数名:程序锁定函数的随机名称池(如 selfLock、systemLock)
9.6 操作说明
- 保存配置:修改完成后点击「保存配置」按钮,配置立即生效(下次注入时使用)
- 重置为默认:点击「重置为默认」按钮,清除所有自定义配置,恢复系统默认值
- 配置文件位置:配置保存在
auth_server/runtime/inject_config.json,可以手动备份或迁移
十三、注入记录
9.1 功能说明
注入记录页面保存所有历史注入操作的记录,方便追溯和重新下载。左侧菜单点击「注入记录」进入。
9.2 记录列表
每条记录展示以下信息:
- ID:记录唯一编号
- 授权码:本次注入使用的PKG_CODE
- 产品:产品标识
- 源文件:上传的源码压缩包文件名
- 大小:源文件大小
- 注入统计:扫描文件数、加载探针数、运行时探针数、CLI探针数
- 状态:成功/失败
- 时间:注入操作时间
9.3 操作功能
| 操作 | 说明 |
| 明细 |
弹窗展示该次注入的完整信息,包括注入统计、注入文件列表(每个文件路径和探针类型)、失败原因(如有) |
| 下载 |
重新下载该次注入好的源码包(输出文件保留在服务器上,可随时重新下载) |
| 删除 |
删除该条记录,同时删除服务器上对应的输出文件 |
9.4 搜索和分页
- 支持按授权码、文件名、产品标识搜索
- 每页显示20条记录,支持分页浏览
⚠️ 注入记录的输出文件会占用服务器存储空间,建议定期清理不需要的旧记录。
十四、设备管理
设备列表展示所有授权包下的部署设备,可以:
- 按PKG_CODE筛选查看某个授权包的设备
- 搜索域名、IP、设备指纹
- 查看每台设备的部署域名、服务器IP、最后上报时间
- 删除异常设备记录(删除后该设备下次上报会重新记录)
💡 如果发现某个授权包下出现大量陌生设备,说明该授权码可能被泄露或倒卖,建议禁用该授权包。
十五、盗版检测与SDK异常
12.1 盗版检测
系统会自动检测注入的代码是否被修改或删除,如果检测到异常即判定为盗版:
- 探针被删除:删除任意一个注入的探针或引用代码,都会触发盗版检测
- 探针被修改:修改注入的探针代码内容,会触发盗版检测
- SDK文件被修改:修改SDK文件夹中的文件,会触发盗版检测
- SDK文件夹被删除:删除整个SDK文件夹,会触发盗版检测
- 恢复正常:如果用户程序覆盖完整代码(恢复所有注入的探针和SDK文件),则判断为正常授权
💡 盗版检测通过设备指纹区分,不同设备的盗版状态独立计算。例如ABC三个指纹在9点时探针被修改判定为3个盗版,10点时B指纹恢复授权,则盗版数量变成2个。仪表盘每分钟自动刷新一次。
12.2 SDK异常检测
系统会自动检测SDK文件夹和里面代码的完整性,如果出现被修改等操作自动上报控制端并锁定:
- SDK目录被删除:独立监控代码检测到SDK目录不存在,立即上报并锁定
- SDK文件被删除:独立监控代码检测到SDK文件不存在,立即上报并锁定
- SDK文件被修改:独立监控代码检测到SDK文件MD5不匹配,立即上报并锁定
- 独立监控代码:随机注入到文件中,平时只监控SDK文件夹和里面代码的完整性,被访问时触发监控并上报异常
12.3 查看盗版和SDK异常
登录后台,在仪表盘可以查看:
- 盗版授权TAB看板:显示当前判定为盗版的设备数量和详细列表
- SDK异常TAB看板:显示当前判定为SDK异常的设备数量和详细列表
- 最近授权请求:显示最近的授权请求记录,包括正常、盗版、SDK异常等状态
- 接口日志:查看详细的接口请求日志,包括sdk_alert和probe_alert等异常类型
12.4 处理盗版和SDK异常
如果发现盗版或SDK异常,可以采取以下措施:
- 禁用授权包:在授权包管理页面禁用对应的授权包,所有使用该授权包的设备都会被锁定
- 禁用单个设备:在设备管理页面禁用单个设备,只影响该设备,不影响其他设备
- 联系客户:如果是误判,可以联系客户确认情况,让客户恢复完整代码
- 记录证据:接口日志和异常上报记录可以作为证据,用于处理纠纷
十六、离线授权检测
13.1 离线判定规则
系统会自动检测设备的上报情况,如果超过48小时没有上报即判定为离线:
- 正常授权:设备在48小时内有上报记录,授权状态正常
- 离线授权:设备超过48小时没有上报,判定为离线
- 恢复正常:如果设备恢复上报,则判定为正常授权
⚠️ 离线判定不代表设备一定有问题,可能是服务器宕机、网络故障、程序未运行等原因。建议先确认情况,再决定是否禁用授权。
13.2 查看离线授权
登录后台,在仪表盘可以查看:
- 离线授权TAB看板:显示当前判定为离线的设备数量和详细列表
- 设备管理:查看每台设备的最后上报时间,判断是否离线
- 接口日志:查看设备的上报记录,确认最后上报时间
13.3 处理离线授权
如果发现设备离线,可以采取以下措施:
- 确认情况:先联系客户确认服务器是否正常运行,网络是否正常
- 等待恢复:如果是临时故障,可以等待设备恢复上报
- 禁用授权:如果确认设备有问题(如客户退款、恶意使用),可以禁用授权包或单个设备
- 调整上报间隔:如果觉得48小时太长或太短,可以在SDK配置中调整上报间隔
十七、接口日志
记录所有业务程序的授权校验请求,包括:
- 请求时间
- PKG_CODE(哪个授权包)
- 产品标识
- 客户端IP
- 授权状态(正常/已禁用/设备超限)
- 返回消息
支持按PKG_CODE、IP、状态筛选搜索,可清空日志。
⚠️ 日志会持续增长,建议定期清理或限制保留天数。
十八、远程SDK手动接入(特殊项目用)
💡 推荐使用「授权注入工具」自动注入(见第九章),无需手动操作。本章仅适用于需要手动接入或特殊项目定制的情况。
⚠️ 远程SDK模式与传统本地SDK模式的区别:远程SDK模式不在目标程序中新增SDK文件夹,所有授权逻辑都在控制端,目标程序中只有远程调用代码(约300行)。安全性更高,维护更方便。
18.1 接入准备
- 在授权后台「产品管理」中添加产品,获取
product_key
- 在「授权包管理」中创建授权包,获取:
pkg_code:包校验码(预埋到目标程序)
verify_key:响应验证密钥(用于验证控制端返回的响应签名)
- 记录授权中台API地址,如:
https://auth.yourdomain.com/api/v1/remote_auth.php
18.2 接入步骤
- 在目标程序根目录创建远程授权配置文件(如
auth_config.php),配置以下参数:
AUTH_SERVER_URL:授权中台API地址
PKG_CODE:包校验码
VERIFY_KEY:响应验证密钥
PRODUCT_KEY:产品标识
REQUEST_INTERVAL:请求间隔(秒),默认60
CACHE_COUNT:缓存机会次数,默认1
- 在目标程序的入口文件(如
index.php)顶部注入远程授权初始化代码
- 在业务程序的多个PHP文件中分散埋入探针(见下方)
- 在关键业务逻辑(如支付、用户注册)前增加授权状态校验
- 测试授权正常、禁用、控制端宕机三种场景
- 打包发给客户
18.3 远程授权初始化代码(入口文件顶部)
if (!defined('AUTH_REMOTE_INIT')) {
define('AUTH_REMOTE_INIT', 1);
require_once __DIR__ . '/auth_config.php';
require_once __DIR__ . '/RemoteAuthClient.php';
$authClient = new RemoteAuthClient([
'server_url' => AUTH_SERVER_URL,
'pkg_code' => PKG_CODE,
'verify_key' => VERIFY_KEY,
'product_key' => PRODUCT_KEY,
'request_interval' => REQUEST_INTERVAL,
'cache_count' => CACHE_COUNT,
]);
$authClient->checkAuth();
}
18.4 四种探针类型
探针1:加载探针(放在各个入口文件顶部,负责初始化授权客户端)
if (!defined('AUTH_SDK_RUN')) {
define('AUTH_SDK_RUN', 1);
require_once __DIR__ . '/RemoteAuthClient.php';
$authClient = new RemoteAuthClient($authConfig);
$authClient->checkAuth();
}
探针2:运行时状态检查探针(散布在业务逻辑中,代码极短,检查授权状态)
if (defined('AUTH_STATUS') && AUTH_STATUS !== 'normal') {
header('HTTP/1.1 503 Service Unavailable');
exit('系统维护中,请稍后再试');
}
探针3:独立监控探针(随机选择一个文件注入,监控本地缓存文件完整性)
// 监控授权缓存文件是否被修改或删除
$authCacheFile = sys_get_temp_dir() . '/auth_cache_' . md5(PKG_CODE) . '.dat';
if (!file_exists($authCacheFile) || md5_file($authCacheFile) !== $expectedMd5) {
// 上报控制端并锁定
$authClient->reportAlert('cache_file_modified');
$authClient->lock();
}
探针4:CLI脚本探针(所有命令行脚本、定时任务顶部)
if (!defined('AUTH_SDK_RUN')) {
define('AUTH_SDK_RUN', 1);
require_once __DIR__ . '/RemoteAuthClient.php';
$authClient = new RemoteAuthClient($authConfig);
$authClient->checkAuth();
}
18.5 探针埋放建议位置
- 所有Web入口:index.php、admin.php、api.php、ajax.php
- 后台控制器父类构造函数
- 数据库模型基类(写操作前)
- 公共函数库文件
- 支付、订单、用户注册等关键业务逻辑前
- 所有CLI定时任务脚本
- 安装向导、升级脚本(防止安装后删除授权)
⚠️ 不要只在一个文件埋探针!分散到至少5-10个文件,增加客户删除/破解的成本。探针之间互相校验,删除任意一个都会被其他探针检测到。
18.6 业务层二次防护(推荐)
在数据库模型基类中,所有写操作前校验授权状态:
// 在 insert/update/delete 前调用
if (defined('AUTH_STATUS') && AUTH_STATUS !== 'normal') {
throw new Exception('系统维护中,暂不可用');
}
// 或者使用全局授权客户端
if (isset($GLOBALS['authClient']) && !$GLOBALS['authClient']->isAuthorized()) {
throw new Exception('系统维护中,暂不可用');
}
18.7 缓存机会机制说明
远程SDK模式使用缓存机会机制平衡安全性和可用性:
- 正常流程:每次请求间隔到期后,向控制端发送授权验证请求,获取最新授权状态
- 控制端连接失败:自动使用上一次缓存的授权结果,缓存机会次数减1
- 缓存机会用完:如果控制端仍然连接不上,程序直接锁定,显示维护页面
- 控制端恢复:下次请求成功后,缓存机会次数重置,程序自动恢复正常
- 缓存不叠加:缓存机会永远只有设定的次数(默认1次),不会因为多次连接成功而累积
18.8 响应签名验证
为了防止中间人攻击和响应篡改,远程SDK模式对控制端返回的响应进行签名验证:
- 控制端使用
verify_key 对响应内容进行HMAC-SHA256签名
- 目标程序收到响应后,使用相同的
verify_key 重新计算签名
- 如果签名不匹配,判定为响应被篡改,程序锁定并上报异常
verify_key 只在授权包创建时生成一次,存储在控制端和目标程序中,不会在网络传输中明文传递
18.9 设备指纹计算
远程SDK模式使用设备指纹区分不同的安装实例:
$deviceFinger = hash('sha256', implode('|', [
$_SERVER['SERVER_ADDR'] ?? '127.0.0.1', // 服务器IP
__DIR__, // 安装目录路径
$_SERVER['HTTP_HOST'] ?? 'cli', // 域名
PHP_VERSION, // PHP版本
PHP_OS, // 操作系统
]));
同一个授权码可以在多个设备上安装,受最大安装数量限制。可以单独禁用某个设备,不影响其他设备。
18.10 Nginx配置(禁止访问授权配置文件)
# 禁止直接访问授权配置文件
location ~* /auth_config\.php$ {
deny all;
return 403;
}
# 禁止访问远程授权客户端文件(如果放在web目录下)
location ~* /RemoteAuthClient\.php$ {
deny all;
return 403;
}
18.11 注意事项
- 远程授权请求使用异步非阻塞方式(fsockopen + register_shutdown_function),用户完全无感知,不影响页面加载速度
- 请求间隔建议设置为30-300秒,间隔越短禁用生效越快,但控制端压力越大
- 缓存机会次数建议设置为1-3次,平衡安全性和可用性
- 控制端禁用授权后,目标程序在请求间隔到期后立即生效,不需要等待本地缓存过期
- 授权逻辑更新只需修改控制端代码,所有已发货的程序立即生效,不需要重新注入发货
- 如果控制端长时间宕机,缓存机会用完后程序会锁定,控制端恢复后自动解锁
十九、代码混淆加密
15.1 功能说明
在授权注入工具中注入时可以选择是否混淆加密代码,避免被看出来或修改配置。混淆加密会对注入的探针代码进行变量名混淆、字符串加密、控制流平坦化等处理,增加破解难度。
⚠️ 混淆加密可能会导致极少数程序出现兼容性问题(如语法错误、运行时错误等)。如果注入后程序无法正常运行,可以尝试关闭混淆加密重新注入。
15.2 使用方法
- 登录后台,点击左侧菜单「授权注入工具」
- 上传源码包或从程序管理中选择程序
- 选择产品、授权包、填写校验码等信息
- 勾选「混淆加密代码」选项
- 点击「开始注入」按钮
- 等待注入完成,下载注入后的源码包
15.3 混淆加密效果
- 变量名混淆:将有意义的变量名替换为随机字符串,增加阅读难度
- 字符串加密:将关键字符串(如URL、常量名、错误信息等)加密,防止被搜索
- 控制流平坦化:将简单的控制流转换为复杂的switch-case结构,增加分析难度
- 每个文件独立混淆:每个文件注入的代码都混淆一次,避免每个文件的代码都一样被针对性删除
15.4 注意事项
- 混淆加密只对注入的探针代码生效,不会修改目标程序的原有代码
- 混淆加密后的代码体积会略有增加(约10%-30%),但不影响运行效率
- 如果注入后程序出现语法错误,可以查看注入日志中的错误信息,或关闭混淆加密重新注入
- 建议在正式发货前先在测试环境验证混淆加密后的程序是否正常运行
二十、案例库(历史问题与解决方案)
16.1 功能说明
系统内置了案例库,记录所有遇到的问题和解决方案,辅助智能判断,避免类似问题再次发生。案例库会在注入前检测、注入过程、注入后验证等环节自动应用,确保注入质量。
✅ 案例库是持续积累的,以后遇到新问题会随时添加到案例库中,不断完善注入器的智能判断能力。
16.2 案例分类
案例库包含以下分类:
- 路径计算问题:相对路径计算、Windows分隔符、前后端分离路径等问题
- 文件类型识别问题:安装文件、引导文件、入口文件、CLI脚本识别等问题
- 常量/变量名问题:包校验码、产品标识、服务器URL、签名密钥、运行时状态等常量名问题
- 语法错误问题:重复方法、文件截断、括号不匹配、浮点数转换、未定义常量、参数类型错误等问题
- 上报逻辑问题:integrity不检查探针、alert不更新设备、锁定不持续上报、异常上报频率过高、首次访问锁定等问题
- 安全检测问题:盗版检测不全面、探针代码相同、独立监控未注入、探针互相校验失效、SDK删除致命错误等问题
- 用户体验问题:安装被阻止、注入位置错误、锁定不持久化、仪表盘不实时、上报阻塞页面等问题
- 特殊程序类型问题:前后端分离、需构建前端、框架程序、SPA单页应用、多入口程序、CLI后台任务/进程守护、运行时探针在控制器类中导致API请求失败等问题
16.3 典型案例
以下是一些典型案例和解决方案:
案例1:注入后破坏进程守护功能
问题:注入后scheduler.php等CLI脚本无法运行,进程守护功能被破坏。
原因:运行时探针在CLI模式下执行,检查LOADER_STATUS常量,但CLI脚本没有被注入加载探针,导致常量未定义,脚本退出。
解决方案:运行时探针增加CLI模式检测(php_sapi_name() !== 'cli'),CLI模式下跳过检查。
案例2:运行时探针在控制器类中导致API请求失败
问题:注入后API请求失败,前端功能无法使用(如扫码识别后创建TOTP任务失败)。
原因:运行时探针被注入到控制器类文件中,API请求加载控制器类时运行时探针执行并退出,输出字符串"系统维护中",前端收到非JSON响应。
解决方案:使用注入策略选择器,有自动加载机制、前后端分离、有CLI脚本的程序使用方案A(保守型),只在入口文件注入运行时探针,不在控制器类中注入。
案例3:独立监控代码相对路径重复
问题:在子目录中的文件,独立监控代码引用的SDK目录路径重复(authcore_xxx/authcore_xxx),导致is_dir()检查失败,误报"SDK目录被删除"。
原因:injectMonitorCodeToFile方法计算的相对路径已经包含了SDK目录名,模板中又追加了{{SDK_DIR}}。
解决方案:在计算相对路径时移除最后一个元素(SDK目录名)。
案例4:SDK模板文件被截断
问题:新注入程序显示"系统维护中",控制端收不到上报。
原因:SDK模板文件AuthClient.php在某行之后被截断,checkProbesIntegrity方法和类没有被正确闭合,导致PHP解析失败,class_exists返回false。
解决方案:补全被截断的方法,确保类正确闭合。
16.4 注入前检查清单
案例库内置了注入前检查清单,包括:
- SDK模板文件检查:检查SDK模板文件是否完整、语法是否正确、类是否正确闭合、是否有重复方法定义
- 目标程序结构检查:检测是否为前后端分离程序、检测后端目录位置、检测前端目录位置、识别所有入口文件、识别安装文件、识别CLI脚本
- 注入过程检查:加载探针100%在文件开头注入、相对路径计算不包含SDK目录名、Windows路径分隔符转换为正斜杠、每个文件探针代码使用独立随机常量名和变量名、安装文件只注入加载探针、根据程序特性自动选择注入方案、运行时探针增加CLI模式检测
- 注入后验证:验证所有注入文件的语法、验证SDK目录路径在所有文件中都正确、验证独立监控代码实际注入、验证探针代码在每个文件中都不一样、验证安装文件没有被注入运行时探针、验证运行时探针只在入口文件中注入、验证控制器类文件没有被注入运行时探针、验证CLI脚本可以正常运行、验证API请求返回正确的JSON格式、验证运行时探针包含CLI模式检测
二十一、退款禁用操作流程
11.1 操作步骤
- 客户申请退款,确认退款后
- 登录授权后台,进入「授权包管理」
- 通过订单号或客户名搜索找到该客户的授权包
- 点击操作列的「禁用」按钮
- 确认禁用
11.2 禁用后效果
- 该授权包下所有部署实例(多台服务器)都会被锁定
- 客户程序本地缓存过期后(最多4小时),下次校验会拿到禁用状态
- 客户网站显示"系统维护中"页面,无法正常使用
- 后台管理功能全部锁死,无法增删改数据
11.3 恢复授权
如果需要恢复(如客户撤销退款),点击「启用」按钮即可恢复。
💡 建议在销售协议中明确写明:本程序为授权使用,退款完成后授权将被远程关闭。避免后续纠纷。
二十二、常见问题
Q1: 授权服务器宕机会不会导致客户网站全部挂掉?
A: 不会。SDK有4小时本地缓存,缓存期内不受影响。连续7次请求失败(约28小时)才会锁定。短暂宕机完全不影响客户使用。
Q2: 客户删除SDK文件怎么办?
A: 探针检测到SDK文件缺失或被篡改,会直接锁定程序。建议在多个文件散布探针,增加删除成本。
Q3: 客户修改缓存文件能绕过吗?
A: 不能。缓存使用AES加密,篡改后解密失败会自动删除缓存并重新请求授权服务器。
Q4: 能做到100%防破解吗?
A: PHP是解释型语言,源码完全交付,无法做到100%绝对防破解。本系统通过多层防护(多探针、加密缓存、完整性校验、运行时常量、数据库钩子)大幅提高破解成本,能挡住95%以上的普通用户。高价程序建议额外做PHP代码混淆。
Q5: 一个授权包最多允许几台设备?
A: 可以在产品设置默认值,也可以在每个授权包单独设置。超过数量后新设备无法使用。
Q6: 2FA验证码总是错误怎么办?
A: 检查手机系统时间是否准确(TOTP依赖时间同步,误差不能超过30秒)。可以开启手机的"自动确定日期和时间"。
Q7: 手机丢了,2FA无法登录怎么办?
A: 可以通过数据库直接关闭2FA:执行SQL UPDATE auth_admin SET totp_enabled=0, totp_secret='' WHERE username='admin';
Q8: 企微收不到通知怎么办?
A: 检查Webhook地址是否正确,点击「发送测试消息」测试。确认服务器能访问外网(企微API地址 qyapi.weixin.qq.com)。
Q9: 如何限制后台只允许特定IP访问?
A: 在Nginx配置中添加:
location /admin/ {
allow 你的IP;
deny all;
# 原有PHP配置...
}
Q10: 接口日志太多怎么清理?
A: 在「接口日志」页面点击「清空日志」。也可以设置定时任务定期清理30天前的日志。
Q11: 注入工具支持哪些源码格式?
A: 目前只支持ZIP格式的源码压缩包。请将整个项目打包为ZIP后上传,最大支持100MB。
Q12: 注入后发现某些关键文件没有注入探针怎么办?
A: 自动注入工具覆盖了绝大多数常见的入口文件和公共文件,但特殊项目结构可能有遗漏。可以:1)查看注入结果页面的文件明细,确认哪些文件被注入了;2)对遗漏的文件手动添加探针(参考第十二章手动接入说明);3)建议优先检查后台入口、API入口、数据库基类等关键文件。
Q13: 注入记录的输出文件会占用服务器空间吗?
A: 是的,每次注入的输出文件都会保存在服务器上(runtime/output目录),方便随时重新下载。建议定期在「注入记录」页面删除不需要的旧记录,释放服务器空间。
Q14: 注入工具处理失败怎么办?
A: 常见原因:1)ZIP文件损坏或格式不正确;2)文件超过100MB限制;3)服务器临时目录不可写;4)PHP的ZipArchive扩展未开启。可以查看注入记录中的失败原因,或检查服务器PHP配置。
Q15: 什么情况下需要修改注入配置?
A: 默认配置适用于绝大多数PHP程序。只有在以下情况才需要修改:1)目标程序的目录结构特殊,注入器无法正确识别入口文件;2)目标程序使用了不常见的文件名,导致探针没有注入到关键文件;3)需要自定义伪装名称,适配特定程序的命名习惯。如果不确定,请保持默认配置。
Q16: 前后端分离的程序注入后,前端构建会覆盖SDK吗?
A: 不会。注入器会自动检测前端构建目录(如 web/dist、public、dist、build 等),SDK会放在PHP后端目录,不会被前端构建覆盖。如果检测不准确,可以在「注入配置」页面手动添加前端构建目录路径。
Q17: 修改注入配置后,之前注入的程序会受影响吗?
A: 不会。配置只对下次注入生效,已注入的程序不受影响。如果需要使用新配置,需要重新注入程序。
Q18: 注入配置保存在哪里?可以备份吗?
A: 配置保存在 auth_server/runtime/inject_config.json 文件中。可以直接复制这个文件进行备份,迁移到其他服务器时只需把这个文件放到对应目录即可。也可以在「注入配置」页面点击「重置为默认」恢复系统默认值。
Q19: 为什么有些文件没有注入探针?
A: 注入器会根据文件类型和内容特征智能判断是否需要注入探针:1)非PHP文件不注入;2)已经包含授权代码的文件跳过;3)被识别为前端构建目录下的文件不注入;4)内容特征不匹配的文件可能不注入。可以在「注入记录」页面查看详细的注入文件列表,确认哪些文件被注入了探针。如果关键文件没有被注入,可以在「注入配置」页面调整识别规则。