Files
YwxAppThink/CHANGELOG.md
T
yangwx 18101cf11a 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(市场 / 开发者中心 / 审核 / 分润)
2026-10-22 00:53:39 +08:00

65 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 更新日志(CHANGELOG)
本项目版本号采用语义化版本(主版本.次版本.修订),唯一事实源是 `config/ywxapp.php` 的 `version`,
由 `scripts/package_framework.php` 递增并写回。发布流程见 `docs/打包与发布指南.md` 的「发版 Checklist」。
## [1.1.2] — 待发布(Unreleased)
一次以「可对外发布」为目标的安全与工程化收敛,未引入新业务功能。
### 安全修复(Security)
- **SEC-1 主框架升级包无来源认证**:官网 / CDN / DNS 被攻破即可向全部客户机推送任意代码。
新增发布包签名体系 `ywxapp\service\PackageVerifier`(RSA-SHA256 签名 + 内容清单哈希 + 防降级),
`FrameworkService::apply()` 解压前强制验签,未部署公钥时 fail-closed;
打包脚本自动签名,配套 `scripts/package_keygen.php` 与 `scripts/package_verify.php`。
- **SEC-2 JWT 默认密钥可用**:`.env.production.example` 键名误写作 `JWT_SECRET_KEY`(代码读 `JWT_SECRET`),
照模板部署等于用公开密钥签发 token。模板键名已修正,`config/jwt.php` 默认密钥改为空,
`JwtService` 签发前强制校验强度(不少于 32 字节且不得命中弱值黑名单)。
- **SEC-3 `/api/*` 文章写接口未授权**:`$noNeedLogin=['*']`,且 `$needRight` 字段 `ApiBase` 根本不认,
任何人可增删改全站文章。白名单收窄为只读的 `index/detail/init`,
写操作需登录且只能操作自己的文章(新增 `assertOwner()`),create 改为字段白名单且归属 `uid` 由服务端写入。
- **SEC-4 后台登录防护缺失**:验证码参数被静默丢弃、账号锁定逻辑从未被调用、后台无限流。
`AdminAuth::login()` 补齐验证码校验、账号锁定 `isLocked()`、IP 与账号双维度限流封禁(配置项 `login_fail_*`)。
- **SEC-5 开发者令牌明文回显且邮箱可枚举**:POST 任意邮箱即返回 token(可用于发布插件、改价、提现)。
改为只发邮件不回显、统一响应文案防枚举、随机延时防时序侧信道、IP 与邮箱限流。
- **SEC-6 模板包 Zip Slip**:`templates/<name>/` 前缀匹配后直接拼接路径,可写入任意目录。
新增模板名白名单、相对路径 `..` 拦截、落盘前 `realpath` 越界校验三道防护。
### 变更(Changed)
- `config/ratelimit.php` 的 RateLimit 中间件仍只注册于 api 应用,后台登录改由 `AdminAuth` 自带计数。
- `.env.production.example` 补齐 `JWT_SECRET`、安全开关、缓存与 Session 驱动、市场角色。
- `config/cache.php` 的 `default`、`config/session.php` 的 `type` 支持 `CACHE_DRIVER` / `SESSION_TYPE`(多副本部署切 redis)。
- `config/ywxapp.php` 新增:`framework_package_verify`、`package_public_key_path`、`login_fail_limit/window/block_time`;
`addon_license_check` 支持 `ADDON_LICENSE_CHECK`。
- `composer.json`:`yansongda/pay`、`hyperf/pimple` 由通配 `*` 锁定到 `^3.7.20` / `^2.2.2`;
`platform-check` 由 false 改 true;`composer.lock` 不再被忽略(可复现构建)。
- 删除 `.travis.yml`(ThinkPHP 官方脚手架残留,含他人加密 deploy key)。
### 升级须知(Breaking)
1. **升级包必须签名**:1.1.2 起的客户机默认要求发布包带 `signature.json`。
自建升级服务器的内网场景可临时用 `FRAMEWORK_PACKAGE_VERIFY=false` 降级(不推荐)。
2. **未配置 `JWT_SECRET` 将无法签发任何 token**(刻意的 fail-closed)。
升级前请执行 `openssl rand -base64 64` 并写入 `.env`。
3. **`/api/v1/article` 的 create / update / delete 需登录**。
此前依赖匿名写库的下游客户端需改为携带 token。
4. **开发者令牌找回页不再回显令牌**,改为邮件发送;
前端 `app/appmall/view/developer/mine.html` 已兼容(无 token 时不展示令牌块)。
### 已知限制与后续(Known Issues)
本节记录本次**未处理**、需要在后续版本跟进的问题,避免它们被误当成「已修复」:
1. **数据库自愈无版本号、无法回滚**:约 60 处模型依赖 `BaseModel.php` 从 `public/install/install.sql` 补表,
且该路径写死在代码里 —— 按安全要求删掉 install 目录后自愈会静默失效;多副本冷启动还存在并发建表竞态。
计划改为「升级 SQL 清单 + 已执行版本表」,自愈降级为兜底。
2. **插件包(addon)尚未接入发布包签名体系**:本次只加固了主框架升级链路。
插件在线安装有 `addon_secret` 下载签名可选调用,但没做包内完整性校验,下一步复用 `PackageVerifier`。
3. **无 CI / 单元测试 / 静态分析**:本次修复的自检均为临时脚本(已删除)。
建议补 `tests/` + GitHub Actions,至少覆盖支付回调签名、Zip 安装路径安全、JWT 密钥策略三条主线。
4. **`catch (\Throwable)` 静默吞异常**:全仓约 144 处(尤以 `BackendSchemaMiddleware`、`BaseModel` 居多),
故障排查成本高,建议逐步替换为「记录 + 上报」。
5. **`app/api/controller/v1` 的 paginate 分页数偏大**(如 1000),缺少服务端上限,建议统一由 `paginate()` 默认限制。