# 更新日志(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//` 前缀匹配后直接拼接路径,可写入任意目录。 新增模板名白名单、相对路径 `..` 拦截、落盘前 `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()` 默认限制。