feat: 上线前安全加固与发布工程化;appmall 由插件迁移为独立应用

安全(P0)
- 发布包签名:新增 scripts/package_keygen.php、scripts/package_verify.php、
  ywxapp\service\PackageVerifier;FrameworkService::apply() 解压前强制验签
  (ywxapp.framework_package_verify,默认开启)
- JWT 收紧:config/jwt.php 移除公开默认密钥,JwtService::assertStrongSecret()
  校验非空 / 长度≥32 / 已知弱值;.env.production.example 键名由 JWT_SECRET_KEY 修正为 JWT_SECRET
- /api/v1/Article:免登录白名单收窄为只读接口,写操作字段白名单 + assertOwner() 越权校验
- 开发者令牌:查找接口不再回显明文、统一失败文案 + 限流
- TemplateInstaller:文件名白名单 + realpath 归一化 + 目录内断言,修复 Zip Slip;补 use ZipArchive
- 后台登录:接入验证码、失败锁定与登录限流(config/ratelimit.php)
- 缓存 / Session 驱动可由 .env 覆盖(CACHE_DRIVER / SESSION_TYPE),集群部署改 redis
- paycenter 支付日志开关改为 PAY_LOG,不再跟随 APP_DEBUG

工程化 / 交付
- 新增 CHANGELOG.md 与 .env.production.example;composer.lock 入库锁定依赖版本
- 插件离线安装 CLI 增加 --uid,后台上传安装透传 uid,付费插件授权校验可通过
- 授权拒绝文案区分「未携带 uid」与「未找到有效授权」,便于排障
- .gitignore 放行 .env.production.example / .env.addon.example / .gitattributes / public/.htaccess

结构
- appmall 由 addon/appmall 迁移为独立应用 app/appmall(市场 / 开发者中心 / 审核 / 分润)
This commit is contained in:
yangwx committed 2026-10-22 00:53:39 +08:00
1 parent 1d49e6f5ee
commit 18101cf11a
636 files changed
+58517 -9519

No files matched your search

+67 -15
View File
@@ -2,9 +2,11 @@
> 基于 ThinkPHP 6 的多应用 + 插件化企业建站/应用市场框架。框架免费,通过插件与模板商业化变现(Discuz! 式闭环:提交 → 审核 → 上架 → 购买 → 支付 → 授权 → 域名绑定 → 运行期巡检 → 分润提现)。
- **版本**:`1.0.16`
- **版本**:`1.1.1`
- **版本单一事实源**:`config/ywxapp.php` 的 `version`(`scripts/package_framework.php` 按它递增并写回)。
修改 README 这里的数字**不会**改变实际版本,发布前请以配置文件为准,并同步更新 `CHANGELOG.md`。
- **官网**:https://www.ywxapp.cn
- **运行环境**:PHP >= 7.4(推荐 8.0+)、MySQL >= 5.7、Redis(可选,用于缓存/队列)
- **运行环境**:PHP >= 8.0(与 `composer.json` 的 require 一致)、MySQL >= 5.7、Redis(可选,用于缓存/队列)
---
@@ -95,13 +97,29 @@ Apache 已内置 `.htaccess`。
```
ywxapp_dev/
├── addon/ # 插件目录(核心业务以插件交付)
│ ├── blog/ # 博客插件
│ ├── forum/ # 论坛插件
├── addon/ # 插件目录(核心业务以插件交付,共 14 个)
│ ├── appmall/ # 应用市场(中心站:购买/授权/分润/审核/开发者中心)
│ ├── articles/ # 内容管理(CMS)插件
│ ├── blog/ # 博客插件
│ ├── demo/ # 演示插件(脚手架样例,仅供学习)
│ ├── docs/ # 站内文档插件(在前台展示 docs/ 下的文档)
│ ├── download/ # 下载中心插件
│ ├── forum/ # 论坛插件
│ ├── haonav/ # 网址导航插件
│ ├── appmall/ # 应用市场(中心站)
│ ├── iot/ # IoT/MQTT 代理插件
│ ├── mqpay/ # 免签支付插件(聚合码 + 商户轮询)
│ ├── seo/ # SEO 优化插件(sitemap/伪静态/路由/内链建议)
│ ├── smsbao/ # 短信宝网关(短信用途)
│ ├── smssend/ # 短信发送插件(聚合发送/日志/成本统计)
│ └── wxchat/ # 微信客服插件
├── scripts/ # 构建工具链(随仓库入库)
│ ├── package_framework.php # 框架整站包(自动排除 config/.env/addon/static)
│ ├── package_addon.php # 单插件包(版本号自动递增)
│ ├── package_all_addons.php # 批量打包插件
│ ├── package_template.php # 模板包
│ ├── submit_template.php # 提交模板
│ ├── framework_files.php # 框架文件清单工具
│ └── framework_files_list.php # 框架文件清单生成器
├── app/ # 多应用(系统级)
│ ├── frontend/ # 企业站/官网(默认首页)
│ ├── backend/ # 后台管理(入口 /admin)
@@ -121,9 +139,10 @@ ywxapp_dev/
├── public/ # Web 根目录
│ ├── install/ # Web 安装器(安装后删除)
│ ├── static/ # 静态资源(插件资源发布到此)
│ └── index.php # 入口
│ └── index.php # 入口(已通过 .htaccess DirectoryIndex 锁定)
├── docs/ # 项目文档与 SQL(插件开发指南/打包发布/应用市场商业化等)
├── runtime/ # 运行时(缓存/日志,可写)
├── extend/ # 扩展目录
├── extend/ # Composer 第三方扩展(框架外引用的库放这里,不走 addon)
├── composer.json
└── README.md
```
@@ -188,7 +207,7 @@ return [
```php
<?php
namespace addons\blog\controller\backend;
namespace addon\blog\controller\backend; // 注意:是 addon\<name>(单数),不是 addons\(复数)
use ywxapp\AddonBase; // 注意:是 AddonBase,不是 Addons
use ywxapp\controller\BackendBase;
@@ -226,11 +245,23 @@ class Article extends BackendBase
| `php think addon:manage [<name>] -a reload [--force] [--status]` | 热重载插件(重导菜单/资源) |
| `php think addon:repair <name> [--menu\|--db\|--config]` | 一键修复:菜单重载 + 数据库自愈 + 配置补全;`<name>` 可为 `all` |
| `php think addon:make <name> -a <action> [--name=<类>]` | 脚手架:生成 controller/model/middleware/validate/event/listener/service/subscribe |
| `php think addon:crud <name> -t <表名> [--name=<类>]` | 按数据表一键生成后台 CRUD(model/controller/view/js + 路由 + 菜单权限) |
| `php think addon:crud --app=backend -t <表名>` | 同样生成,但落到核心后台 `app/backend`(权限直写 backend_power) |
| `php think db:backup [-t <表名>] [--keep=<N>]` | 数据库备份(纯 PHP 实现,可挂定时任务) |
| `php think attachment:clean [--delete]` | 清理没有附件记录的孤儿文件(默认只统计) |
| `php think addon:health` | 插件健康检测(依赖/表/菜单完整性) |
| `php think addon:license-check` | 运行期授权校验 |
| `php think ywxapp:upgrade` | 框架在线升级(`framework` 路由配套) |
| `php think app` | 应用生成器(生成多应用骨架:frontend/backend/member/api) |
| `php think workerman:gateway` | Workerman GatewayWorker(配合 `addon/wxchat` 客服通道) |
| `php think iot` / `iot:acltest` / `iot:probe` | `addon/iot` 套件命令(综合 / ACL 自检 / 链路探测) |
| `php think haonav:checklinks` | `addon/haonav` 死链/健康度巡检 |
| `php think wxchat:server` | `addon/wxchat` GatewayWorker 长连服务(`-a start/stop/status/reload`) |
示例:
> 命令通过 `ywxapp/service/AppService.php::boot()` 的 `commands()` 注册,
> 插件级命令在其自身 `addon/<name>/command/*.php` 中声明 `setName(...)`,
> AppService 启动时统一由 `Console::starting()` 回调加载并校验类名(坏类名/非 Command 子类会被 `addCommands` 自动跳过,单个插件出错不影响整体)。
> 早期(≤4.0)的 `config/console.php` 注册表为空数组 `[[]]`,**无效**。
```bash
# 安装 blog 插件(开发者模式)
@@ -259,15 +290,22 @@ php think addon:make blog -a controller --name=backend/Stat
### 中心站 / 客户机模式
由 `config/ywxapp.php` 的 `market_mode`(auto/center/client)决定,`auto` 时按 `api_url` 推导(空=中心站,指向他机=客户机)。解耦设计:中心站逻辑全在 `addon/appmall/`,`ywxapp/`、`app/` 禁直读 `appmall_*` 表;插件控制器只做分发(客户机 → 远程服务,中心站 → `MarketService`,缺失 → 503)。
由 `config/ywxapp.php` 的 `market_mode`(auto/center/client)决定,`auto` 时按 `api_url` 推导(空=中心站,指向他机=客户机)。解耦设计:中心站逻辑全在 `app/appmall/`(原 `addon/appmall` 已迁为普通应用,URL 前缀 `/appmall` 不变),`ywxapp/` 及 `app/` 下其它应用禁直读 `appmall_*` 表;核心控制器只做分发(客户机 → 远程服务,中心站 → `MarketService`,缺失 → 503)。
---
## 九、打包与分发
- 插件包:`scripts/package_addon.php`(版本号自动递增)
- 框架包:`scripts/package_framework.php`(排除 `config/`、`.env`、`addon/`、`public/static/<插件名>/`)
- 升级:`AddonService::onlineUpgrade($version)`;`importsql` 仅放行 `CREATE TABLE`/`INSERT`,拒绝 `ALTER`/`DROP`(旧库迁移须手动 `RENAME TABLE`)
构建工具链全部位于 `scripts/`(随仓库入库,请勿加入 `.gitignore`):
- 单插件包:`scripts/package_addon.php`(版本号自动递增)
- 批量插件包:`scripts/package_all_addons.php`(一次性把全部 enabled 插件打成 zip)
- 框架整站包:`scripts/package_framework.php`(排除 `config/`、`.env`、`addon/`、`public/static/<插件名>/`)
- 模板包:`scripts/package_template.php`
- 模板提交:`scripts/submit_template.php`
- 文件清单:`scripts/framework_files.php` / `scripts/framework_files_list.php`
升级流程:`AddonService::onlineUpgrade($version)`;`importsql` 仅放行 `CREATE TABLE`/`INSERT`,拒绝 `ALTER`/`DROP`(旧库迁移须手动 `RENAME TABLE`)。
---
@@ -293,9 +331,23 @@ php think addon:make blog -a controller --name=backend/Stat
## 十一、许可与商业化
- 框架核心基于 ThinkPHP 协议,免费使用。
- 商业化通过 `addon/appmall` 应用市场分发插件与模板,支持购买、授权、域名绑定、分润提现。
- 商业化通过 `app/appmall` 应用市场分发插件与模板,支持购买、授权、域名绑定、分润提现。
- 详细商业化与运营文档见 `docs/`。
---
## 上线与运维文档索引
| 文档 | 用途 |
| --- | --- |
| `docs/生产部署清单.md` | 生产环境部署必读:Nginx/PHP 配置、`.env` 安全项、目录权限、定时任务、常驻进程、多副本注意事项、上线后 10 分钟自检 |
| `docs/打包与发布指南.md` | 发版流程:三种产物(整包/补丁/安装包)、**发布包签名**、热点补丁模式、发版 Checklist |
| `CHANGELOG.md` | 版本变更记录与 Breaking 变更说明 |
> 发布前必做:`php scripts/package_keygen.php`(一次)→ `php scripts/package_framework.php <版本>`
> → 确认三个包的 `sign` 均为「已签名」→ `php scripts/package_verify.php <zip> <版本>` 验签。
---
© 2026-2036 YwxApp. All rights reserved. https://www.ywxapp.cn