📚 PHP授权控制系统 使用教程

从部署到使用,完整图文指南

一、系统简介

PHP多产品通用授权控制系统,用于售卖PHP网站程序时的授权管理。核心功能:

二、部署安装

2.1 环境要求

2.2 部署步骤

  1. 创建数据库:新建数据库,编码选择 utf8mb4
  2. 导入数据表:将 auth_server/db.sql 导入数据库
  3. 修改配置:编辑 auth_server/config.php,填写数据库连接信息
  4. 上传文件:将 auth_server 目录上传到服务器,绑定域名
  5. 配置Web服务器:参考项目中的 nginx.conf 配置Nginx
💡 宝塔面板用户:直接在宝塔添加站点,根目录指向 auth_server,PHP版本选择7.4以上,在配置文件中禁止访问 lib 和 config 目录即可。

2.3 已部署用户升级(v1.0 → v1.1)

如果已经部署了v1.0版本,执行以下操作升级:

  1. 备份数据库和现有文件
  2. 在数据库中执行 upgrade_v1.1.sql 升级脚本
  3. 上传新的文件覆盖旧文件(config.php 除外,保留你的数据库配置)
  4. 刷新页面即可使用2FA和Webhook新功能

三、登录系统

3.1 默认账号

用户名密码
adminpassword
⚠️ 首次登录后请立即修改密码!默认密码存在安全风险。

3.2 登录安全机制

3.3 修改密码

登录后,点击左侧菜单「修改密码」,输入原密码和新密码即可。新密码至少8位。

四、两步验证 (2FA)

4.1 什么是2FA

两步验证(Two-Factor Authentication)是在密码之外增加的第二重身份验证。启用后,登录时需要:

  1. 输入用户名和密码(第一步)
  2. 输入身份验证器APP中的6位动态验证码(第二步)

即使密码泄露,没有你的手机也无法登录,大幅提升账户安全性。

4.2 支持的身份验证器

4.3 启用2FA步骤

  1. 登录后台,点击左侧菜单「安全设置」
  2. 找到「两步验证」区域,点击「开始绑定2FA」
  3. 用手机上的身份验证器APP扫描页面上的二维码
  4. (无法扫描时)手动输入页面显示的密钥
  5. 验证器APP会显示6位动态验证码,输入到页面输入框
  6. 点击「确认启用2FA」,绑定成功
⚠️ 绑定成功后,请务必保存好密钥和恢复码。如果手机丢失,将无法登录!建议同时在多个设备上绑定。

4.4 关闭2FA

在「安全设置」页面,输入登录密码后点击「关闭2FA」即可。

4.5 验证码错误怎么办

五、多渠道通知系统(推荐)

5.1 功能说明

多渠道通知系统是对原有企业微信Webhook通知的全面升级,支持多种推送渠道、多个Webhook地址、按事件类型订阅,让你第一时间掌握授权系统的所有动态。

支持的推送渠道:

支持的15种事件类型:

分类事件类型触发时机
系统登录管理员登录成功后台管理员登录成功时
管理员登录失败后台管理员登录失败时
2FA验证失败二次验证失败时
授权包授权包禁用授权包被禁用时
授权包启用授权包被启用时
授权包删除授权包被删除时
设备新设备上报新设备首次上报授权时
设备禁用设备被禁用时
设备启用设备被启用时
异常检测SDK异常SDK文件被修改或删除时
授权异常签名验证失败、授权包不存在时
盗版检测注入代码被修改或删除时
注入操作注入成功授权注入成功时
注入失败授权注入失败时

5.2 核心特性

5.3 添加Webhook

  1. 登录后台,点击左侧菜单「通知设置」
  2. 点击右上角「+ 添加Webhook」按钮
  3. 填写名称(如"企微告警群"、"钉钉运维群")
  4. 选择渠道(企业微信/钉钉/飞书/自定义)
  5. 粘贴Webhook地址
  6. 如果是钉钉或飞书,且开启了加签,填写签名密钥(可选)
  7. 勾选需要订阅的事件(默认全部勾选)
  8. 点击「添加」按钮
  9. 添加成功后,点击「测试」按钮,验证Webhook是否可用

5.4 获取各渠道Webhook地址

企业微信:

  1. 打开企业微信,进入要接收通知的群聊
  2. 点击右上角「...」→「群机器人」→「添加机器人」
  3. 给机器人起个名字,点击「添加」
  4. 复制机器人的Webhook地址

钉钉:

  1. 打开钉钉,进入要接收通知的群聊
  2. 点击右上角「...」→「智能群助手」→「添加机器人」
  3. 选择「自定义」机器人
  4. 给机器人起个名字,选择安全设置(建议使用加签)
  5. 点击「完成」,复制Webhook地址和加签密钥

飞书:

  1. 打开飞书,进入要接收通知的群聊
  2. 点击右上角「设置」→「群机器人」→「添加机器人」
  3. 选择「自定义机器人」
  4. 给机器人起个名字,选择安全设置(建议使用签名校验)
  5. 点击「添加」,复制Webhook地址和签名密钥

5.5 管理Webhook

5.6 查看推送日志

在通知设置页面下方,可以查看所有推送日志,支持按Webhook、事件类型、状态筛选。

5.7 安全机制

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 添加产品

  1. 点击左侧菜单「产品管理」
  2. 点击「+ 添加产品」
  3. 填写产品标识(英文唯一,如 shop_v1)
  4. 填写产品名称(如"商城系统V1")
  5. 设置默认最大部署设备数(每个授权包默认允许几台服务器使用)
  6. 选择状态(启用/禁用)
  7. 点击「确认添加」
💡 产品标识一旦创建不可修改,用于SDK中标识产品归属。A产品的授权码不能在B产品上使用。

6.3 编辑/删除产品

七、程序管理(预存未注入程序)

7.1 功能说明

程序管理允许你预存未注入的程序源码,在授权注入工具中可以直接选择程序管理中的程序,无需每次都上传。适合经常需要注入的程序,可以节省上传时间,提高效率。

💡 程序管理中存储的是未注入的原始程序,注入时会从程序管理中复制一份进行注入,不会修改原始程序。可以随时更新程序管理中的程序版本。

7.2 上传程序

  1. 点击左侧菜单「程序管理」
  2. 点击「+ 上传程序」
  3. 填写程序名称(如"商城系统V1.2")
  4. 填写程序版本(如"v1.2.0")
  5. 选择程序文件(ZIP格式,最大支持100MB)
  6. 填写备注(可选,用于记录程序的特殊说明)
  7. 点击「确认上传」

7.3 管理程序

7.4 在注入工具中使用

  1. 点击左侧菜单「授权注入工具」
  2. 在「程序来源」中选择「从程序管理选择」
  3. 在下拉列表中选择需要注入的程序
  4. 选择产品、授权包、填写校验码等信息
  5. 点击「开始注入」按钮
  6. 等待注入完成,下载注入后的源码包
✅ 使用程序管理的优势:1)无需每次上传,节省时间;2)原始程序统一管理,版本清晰;3)注入时从程序管理复制,不会修改原始程序;4)可以随时更新程序版本。

7.5 注意事项

八、授权包管理(核心功能)

7.1 什么是授权包

每卖出一份程序,生成一个授权包(PKG_CODE)。这个授权码会预埋到客户拿到的源码中,作为该客户的唯一身份标识。

7.2 生成授权包

  1. 点击左侧菜单「授权包管理」
  2. 点击「+ 生成授权包」
  3. 选择产品(这款程序属于哪个产品)
  4. 填写订单号(对应你的销售订单,方便查找)
  5. 填写客户姓名、联系方式(可选,方便售后)
  6. 设置最大设备数(0=使用产品默认值,也可单独设置)
  7. 填写备注(可选)
  8. 点击「生成授权包」

生成后会得到一个唯一的 PKG_CODE,如 PKG20260830123456789。

7.3 授权包状态

状态说明
正常授权有效,客户程序正常运行
已禁用授权被禁用(通常是退款),客户程序会被锁定

7.4 查看授权包下的设备

点击授权包操作列的「设备」按钮,可以查看该授权码被部署到了哪些服务器,包括:

7.5 编辑授权包

点击「编辑」可以修改订单号、客户信息、最大设备数、备注。PKG_CODE和产品不可修改。

九、授权注入工具(推荐)

✅ 推荐使用自动注入工具:上传源码压缩包,系统自动完成SDK注入、校验码修改、探针埋入,无需手动操作,省时省力且不易出错。

8.1 功能说明

授权注入工具可以自动完成以下所有操作:

  1. 解压ZIP源码包,自动识别源码根目录
  2. 复制 client_sdk SDK目录到源码根目录
  3. 自动修改校验码:将选择的授权包PKG_CODE写入SDK配置
  4. 自动写入产品标识、授权服务器URL
  5. 自动创建runtime缓存目录和.htaccess保护
  6. 自动扫描所有PHP文件,智能识别文件类型并埋入对应探针
  7. 自动跳过已有授权代码的文件,避免重复注入
  8. 重新打包为ZIP,提供下载

8.2 使用步骤

  1. 登录后台,点击左侧菜单「授权注入工具」
  2. 点击上传区域,选择你的源码压缩包(ZIP格式,最大100MB)
  3. 下拉选择对应的授权包(系统自动获取PKG_CODE)
  4. 点击「开始自动注入」按钮
  5. 等待处理完成(页面显示进度条和当前步骤)
  6. 查看注入结果和注入文件明细
  7. 点击「下载注入后的源码包」,直接发给客户

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 注入结果页面

注入完成后,结果页面展示:

💡 建议注入后抽查几个关键入口文件,确认探针已正确埋入。不同项目结构不同,自动注入覆盖了绝大多数常见情况,特殊项目可能需要手动补充个别探针。

8.5 处理时间参考

源码包大小预计耗时
< 5MB2-5秒
5-30MB10-30秒
30-100MB30-90秒

主要耗时在解压ZIP和重新打包ZIP,探针注入本身很快。处理期间请勿关闭或刷新页面。

十、远程SDK授权模式(更安全,推荐)

10.1 什么是远程SDK授权模式

远程授权模式是一种全新的授权注入方式,与传统的本地SDK模式不同:

💡 推荐场景:对安全性要求高、需要实时禁用、经常需要更新授权逻辑的场景。传统本地SDK模式仍然保留,适合对可用性要求极高、控制端可能长时间不可用的场景。

10.2 与本地SDK模式对比

对比项本地SDK模式(传统)远程授权模式(推荐)
新增文件1个SDK文件夹(2-3个文件)0个文件,所有代码注入到已有文件
目标程序注入代码量约1600行(含SDK完整逻辑)约300行(远程调用+探针+监控)
授权逻辑位置目标程序中(可被反编译)控制端(无法获取)
secret_key安全性目标程序中(可被反编译)只在控制端,目标程序只有verify_key
禁用生效时间需等缓存过期(最长4小时)请求间隔到期后立即生效(默认60秒)
控制端宕机影响无(本地缓存可离线使用)缓存机会用完后锁定(默认1次机会)
SDK更新维护需重新注入发货控制端更新即生效
隐藏性⭐⭐⭐(SDK文件夹可见)⭐⭐⭐⭐⭐(无新增文件)
整体安全性⭐⭐⭐⭐⭐⭐⭐⭐

10.3 使用方法

在「授权注入工具」页面的「授权模式」选项中选择「远程授权模式」,然后配置以下参数:

⚠️ 注意:远程授权模式需要目标程序的服务器能够访问控制端域名(HTTPS)。如果目标程序的服务器无法访问外网,或控制端域名可能变更,请使用本地SDK模式。

10.4 工作原理

远程授权模式的工作流程如下:

  1. 代码注入:注入器自动识别目标程序的公共引导文件(如common.php、bootstrap.php),将远程授权核心代码(约200行)注入到该文件开头;同时在入口文件注入轻量探针,在配置文件注入独立监控代码。
  2. 首次访问:用户访问目标程序时,远程授权代码自动执行,异步发起HTTP请求到控制端的remote_auth.php接口,传递授权码、设备指纹、域名等信息。
  3. 异步执行:请求使用fsockopen非阻塞方式发出,页面立即开始渲染,用户完全无感知。页面渲染完成后(register_shutdown_function),才读取控制端的响应。
  4. 缓存管理:控制端返回授权状态后,结果加密存储到系统临时目录(sys_get_temp_dir),文件名随机,内容XOR加密。下次访问时,如果未到请求间隔,直接使用缓存。
  5. 缓存失败降级:如果系统临时目录不可写(缓存失败),自动降级为每次请求都连接控制端,不锁定程序,确保可用性。
  6. 连接失败处理:如果控制端连接失败,使用缓存机会(默认1次)。缓存机会用完后,如果仍然连接失败,程序锁定,显示维护页面。
  7. 连接恢复:控制端恢复连接后,自动解锁,缓存机会刷新,程序恢复正常使用。
  8. 独立监控:配置文件中的独立监控代码会校验公共引导文件中的授权核心代码是否被删除或修改,如果发现异常,立即上报控制端并锁定程序。

10.5 缓存机会机制详解

缓存机会是远程授权模式的核心容错机制,平衡安全性和可用性:

时间线示例(请求间隔=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响应签名验证:

10.7 设备指纹

远程授权模式使用与本地SDK模式相同的设备指纹算法,基于以下信息生成唯一的设备指纹(SHA-256):

同一授权包下的不同设备通过设备指纹区分,支持单设备禁用(不需要禁用整个授权包)。

10.8 注意事项

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文件都注入运行时探针简单程序、单文件程序、没有自动加载机制的程序
DAPI专用型只在API入口文件和API控制器中注入纯API服务、前后端分离的后端、微服务、RESTful API
E后台专用型只在后台入口文件和后台控制器中注入有后台管理面板的程序、CMS系统、企业管理系统
F核心文件型只在核心文件(入口、配置、核心类、基类)中注入大型程序、复杂程序、框架程序、需要最小化性能影响的程序

9.3 程序特性自动检测

注入器会自动检测以下程序特性,用于选择注入方案:

9.4 自动选择逻辑

注入器根据以下规则自动选择注入方案(优先级从高到低):

  1. 纯API服务(有REST API、有API控制器、没有模板引擎、没有后台管理面板)→ 方案D(API专用型)
  2. 有后台管理面板且没有前台(有后台控制器、有后台目录、没有模板引擎)→ 方案E(后台专用型)
  3. 大型复杂程序(PHP文件超过50个、有核心类、有服务容器、有事件系统)→ 方案F(核心文件型)
  4. 有自动加载机制 → 方案A(保守型)
  5. 前后端分离 → 方案A(保守型)
  6. 有CLI脚本/进程守护 → 方案A(保守型)
  7. 有控制器类且有命名空间 → 方案B(均衡型)
  8. 简单程序(PHP文件少于10个,没有自动加载,没有控制器类)→ 方案C(严格型)
  9. 默认 → 方案A(保守型)

9.5 查看注入策略选择结果

注入完成后,可以在注入日志中查看注入策略选择结果:

  1. 登录后台,点击左侧菜单「注入记录」
  2. 点击对应注入记录的「查看明细」
  3. 在注入日志中可以看到「【注入策略】自动选择方案X」以及选择原因
  4. 也可以在注入文件明细中查看每个文件注入的探针类型

9.6 运行时探针CLI模式检测

所有注入方案的运行时探针都包含CLI模式检测,在CLI模式下(`php_sapi_name() === 'cli'`)会跳过运行时探针检查,避免破坏进程守护/后台任务。

✅ 已解决的问题:之前注入后会破坏进程守护功能(如scheduler.php),原因是运行时探针在CLI模式下执行并退出。现在运行时探针增加了CLI模式检测,CLI模式下跳过检查,进程守护功能可以正常运行。

9.7 注入后验证

注入完成后,注入器会自动执行6项验证检查,确保注入质量:

  1. SDK完整性检查:SDK目录和文件是否存在,语法是否正确,类定义是否完整
  2. 注入文件语法检查:所有注入文件的语法是否正确,路径引用是否正确
  3. 安装文件保护检查:安装文件(install.php、setup.php等)没有被注入运行时探针
  4. 独立监控验证:独立监控代码至少注入2个文件
  5. 探针多样性检查:每个文件的探针代码都不一样(防止批量搜索删除)
  6. 运行时探针CLI模式检测检查:运行时探针包含CLI模式检测

验证结果会记录在注入日志中,如果发现问题会显示警告或错误信息。

十二、注入配置(高级功能)

9.1 功能说明

注入配置页面允许你可视化修改注入器的各项识别规则和伪装名称,适配不同结构的PHP程序。左侧菜单点击「注入配置」进入。

提示:配置保存后,下次注入时生效。已注入的程序不受影响。如果不确定如何配置,请保持默认值。

9.2 文件识别配置

控制注入器如何识别不同类型的PHP文件,决定使用哪种探针:

9.3 入口文件内容特征配置

通过文件内容特征进一步判断是否为真正的入口文件,避免误判:

9.4 前端构建目录检测

注入器会自动检测项目中的前端构建目录,确保SDK不放在这些目录下,避免前端构建时被覆盖。

检测依据(多重判断):

前后端分离程序:如果目标程序是前后端分离的,注入器会自动识别前端构建目录,SDK会放在PHP后端目录,不会被前端构建覆盖。

9.5 伪装名称配置

控制注入器随机生成的目录名、文件名、常量名、函数名等,伪装成项目中常见的名称,避免被破解者针对性搜索删除:

9.6 操作说明

十三、注入记录

9.1 功能说明

注入记录页面保存所有历史注入操作的记录,方便追溯和重新下载。左侧菜单点击「注入记录」进入。

9.2 记录列表

每条记录展示以下信息:

9.3 操作功能

操作说明
明细 弹窗展示该次注入的完整信息,包括注入统计、注入文件列表(每个文件路径和探针类型)、失败原因(如有)
下载 重新下载该次注入好的源码包(输出文件保留在服务器上,可随时重新下载)
删除 删除该条记录,同时删除服务器上对应的输出文件

9.4 搜索和分页

⚠️ 注入记录的输出文件会占用服务器存储空间,建议定期清理不需要的旧记录。

十四、设备管理

设备列表展示所有授权包下的部署设备,可以:

💡 如果发现某个授权包下出现大量陌生设备,说明该授权码可能被泄露或倒卖,建议禁用该授权包。

十五、盗版检测与SDK异常

12.1 盗版检测

系统会自动检测注入的代码是否被修改或删除,如果检测到异常即判定为盗版:

💡 盗版检测通过设备指纹区分,不同设备的盗版状态独立计算。例如ABC三个指纹在9点时探针被修改判定为3个盗版,10点时B指纹恢复授权,则盗版数量变成2个。仪表盘每分钟自动刷新一次。

12.2 SDK异常检测

系统会自动检测SDK文件夹和里面代码的完整性,如果出现被修改等操作自动上报控制端并锁定:

12.3 查看盗版和SDK异常

登录后台,在仪表盘可以查看:

  1. 盗版授权TAB看板:显示当前判定为盗版的设备数量和详细列表
  2. SDK异常TAB看板:显示当前判定为SDK异常的设备数量和详细列表
  3. 最近授权请求:显示最近的授权请求记录,包括正常、盗版、SDK异常等状态
  4. 接口日志:查看详细的接口请求日志,包括sdk_alert和probe_alert等异常类型

12.4 处理盗版和SDK异常

如果发现盗版或SDK异常,可以采取以下措施:

  1. 禁用授权包:在授权包管理页面禁用对应的授权包,所有使用该授权包的设备都会被锁定
  2. 禁用单个设备:在设备管理页面禁用单个设备,只影响该设备,不影响其他设备
  3. 联系客户:如果是误判,可以联系客户确认情况,让客户恢复完整代码
  4. 记录证据:接口日志和异常上报记录可以作为证据,用于处理纠纷

十六、离线授权检测

13.1 离线判定规则

系统会自动检测设备的上报情况,如果超过48小时没有上报即判定为离线:

⚠️ 离线判定不代表设备一定有问题,可能是服务器宕机、网络故障、程序未运行等原因。建议先确认情况,再决定是否禁用授权。

13.2 查看离线授权

登录后台,在仪表盘可以查看:

  1. 离线授权TAB看板:显示当前判定为离线的设备数量和详细列表
  2. 设备管理:查看每台设备的最后上报时间,判断是否离线
  3. 接口日志:查看设备的上报记录,确认最后上报时间

13.3 处理离线授权

如果发现设备离线,可以采取以下措施:

  1. 确认情况:先联系客户确认服务器是否正常运行,网络是否正常
  2. 等待恢复:如果是临时故障,可以等待设备恢复上报
  3. 禁用授权:如果确认设备有问题(如客户退款、恶意使用),可以禁用授权包或单个设备
  4. 调整上报间隔:如果觉得48小时太长或太短,可以在SDK配置中调整上报间隔

十七、接口日志

记录所有业务程序的授权校验请求,包括:

支持按PKG_CODE、IP、状态筛选搜索,可清空日志。

⚠️ 日志会持续增长,建议定期清理或限制保留天数。

十八、远程SDK手动接入(特殊项目用)

💡 推荐使用「授权注入工具」自动注入(见第九章),无需手动操作。本章仅适用于需要手动接入或特殊项目定制的情况。
⚠️ 远程SDK模式与传统本地SDK模式的区别:远程SDK模式不在目标程序中新增SDK文件夹,所有授权逻辑都在控制端,目标程序中只有远程调用代码(约300行)。安全性更高,维护更方便。

18.1 接入准备

  1. 在授权后台「产品管理」中添加产品,获取 product_key
  2. 在「授权包管理」中创建授权包,获取:
    • pkg_code:包校验码(预埋到目标程序)
    • verify_key:响应验证密钥(用于验证控制端返回的响应签名)
  3. 记录授权中台API地址,如:https://auth.yourdomain.com/api/v1/remote_auth.php

18.2 接入步骤

  1. 在目标程序根目录创建远程授权配置文件(如 auth_config.php),配置以下参数:
    • AUTH_SERVER_URL:授权中台API地址
    • PKG_CODE:包校验码
    • VERIFY_KEY:响应验证密钥
    • PRODUCT_KEY:产品标识
    • REQUEST_INTERVAL:请求间隔(秒),默认60
    • CACHE_COUNT:缓存机会次数,默认1
  2. 在目标程序的入口文件(如 index.php)顶部注入远程授权初始化代码
  3. 在业务程序的多个PHP文件中分散埋入探针(见下方)
  4. 在关键业务逻辑(如支付、用户注册)前增加授权状态校验
  5. 测试授权正常、禁用、控制端宕机三种场景
  6. 打包发给客户

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 探针埋放建议位置

⚠️ 不要只在一个文件埋探针!分散到至少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模式使用缓存机会机制平衡安全性和可用性:

18.8 响应签名验证

为了防止中间人攻击和响应篡改,远程SDK模式对控制端返回的响应进行签名验证:

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 注意事项

十九、代码混淆加密

15.1 功能说明

在授权注入工具中注入时可以选择是否混淆加密代码,避免被看出来或修改配置。混淆加密会对注入的探针代码进行变量名混淆、字符串加密、控制流平坦化等处理,增加破解难度。

⚠️ 混淆加密可能会导致极少数程序出现兼容性问题(如语法错误、运行时错误等)。如果注入后程序无法正常运行,可以尝试关闭混淆加密重新注入。

15.2 使用方法

  1. 登录后台,点击左侧菜单「授权注入工具」
  2. 上传源码包或从程序管理中选择程序
  3. 选择产品、授权包、填写校验码等信息
  4. 勾选「混淆加密代码」选项
  5. 点击「开始注入」按钮
  6. 等待注入完成,下载注入后的源码包

15.3 混淆加密效果

15.4 注意事项

二十、案例库(历史问题与解决方案)

16.1 功能说明

系统内置了案例库,记录所有遇到的问题和解决方案,辅助智能判断,避免类似问题再次发生。案例库会在注入前检测、注入过程、注入后验证等环节自动应用,确保注入质量。

✅ 案例库是持续积累的,以后遇到新问题会随时添加到案例库中,不断完善注入器的智能判断能力。

16.2 案例分类

案例库包含以下分类:

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 注入前检查清单

案例库内置了注入前检查清单,包括:

  1. SDK模板文件检查:检查SDK模板文件是否完整、语法是否正确、类是否正确闭合、是否有重复方法定义
  2. 目标程序结构检查:检测是否为前后端分离程序、检测后端目录位置、检测前端目录位置、识别所有入口文件、识别安装文件、识别CLI脚本
  3. 注入过程检查:加载探针100%在文件开头注入、相对路径计算不包含SDK目录名、Windows路径分隔符转换为正斜杠、每个文件探针代码使用独立随机常量名和变量名、安装文件只注入加载探针、根据程序特性自动选择注入方案、运行时探针增加CLI模式检测
  4. 注入后验证:验证所有注入文件的语法、验证SDK目录路径在所有文件中都正确、验证独立监控代码实际注入、验证探针代码在每个文件中都不一样、验证安装文件没有被注入运行时探针、验证运行时探针只在入口文件中注入、验证控制器类文件没有被注入运行时探针、验证CLI脚本可以正常运行、验证API请求返回正确的JSON格式、验证运行时探针包含CLI模式检测

二十一、退款禁用操作流程

11.1 操作步骤

  1. 客户申请退款,确认退款后
  2. 登录授权后台,进入「授权包管理」
  3. 通过订单号或客户名搜索找到该客户的授权包
  4. 点击操作列的「禁用」按钮
  5. 确认禁用

11.2 禁用后效果

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)内容特征不匹配的文件可能不注入。可以在「注入记录」页面查看详细的注入文件列表,确认哪些文件被注入了探针。如果关键文件没有被注入,可以在「注入配置」页面调整识别规则。

← 返回登录页