CDN 加速:加启用复选框 + 预制白名单与黑名单,勾了不填地址要提示 #4

Closed
opened 2026-10-25 08:23:32 +00:00 by laoyang · 2 comments
Owner

需求

在 3.2.34 的 CDN 加速功能上补三件事。

1. 加一个「启用 CDN 加速」复选框

当前设计是「CDN 地址留空即关闭」。改成显式开关:

  • 复选框未勾 → 功能完全关闭,不管地址和规则填了什么
  • 复选框勾选 + 地址已填 → 生效
  • 复选框勾选 + 地址为空 → 不允许,保存时要提示「这个必须填」

2. 白名单给一份预制项(写死在主题里)

预制内容(用户指定,13 个后缀):

.avif  .css  .gif  .jpeg  .jpg  .js  .json  .mp3  .mp4  .pdf  .png  .svg  .webp

3. 黑名单也给一份预制项

放「跟安全相关、本来就绝不该走 CDN」的后缀,例如 .php 一类。

4. 生效条件(用户原话整理)

  1. 两个预制列表本身不产生任何作用,只是默认值。
  2. 只有勾了复选框 + 填了 CDN 地址,预制白名单和预制黑名单才参与匹配。
  3. 只勾复选框、没填地址 → 不行,要提示必须填。

设计决定(需确认是否同意)

预制项硬编码在主题代码里,运行时无条件参与匹配;输入框里放的只有用户额外补充的规则,两者叠加。

理由:

  1. std 在运行时完全不起作用 —— Options Framework 的 std 只服务「后台预填」和「恢复默认」,kratos_option() 取值时压根不看它。所以把预制项写进 std,老站点(已保存过配置的)取到的仍然是空值,预制等于不存在。
  2. 预制项若写进输入框,用户误删一条就静默失效,且升级时预制列表无法更新。
  3. 硬编码之后,用户想排除某个预制项,可以在黑名单里写它(黑名单优先),不需要去改输入框。

输入框的说明文字里会列出预制了什么,用户看得见。

写法确认

预制项统一用带点写法(.avif 而不是 avif)。

原因:规则引擎里单个纯字母词会同时按「扩展名」与「路径子串」匹配(这是为了救 uploads 那条规则)。avif 作子串会命中 /wp-content/uploads/avif-optimized/a.jpg 这类路径;带点之后子串是 .avif,不会误伤。

验收标准

  1. 后台「CDN 加速」页第一个控件是复选框,未勾时前台零变化。
  2. 勾选但地址留空,点保存要报错并提示必须填,配置不被保存。
  3. 勾选 + 填地址后,.jpg .css 等 13 类资源走 CDN。
  4. 预制白名单生效时,.php 等不在预制的资源仍保持原地址。
  5. 用户在白名单输入框额外写规则,与预制项叠加(不是替换)。
  6. 用户在白名单输入框写 *,预制黑名单仍然挡住它。
  7. 地址清空但保持勾选并存盘,前台零变化(合法状态,只是没生效)。
## 需求 在 3.2.34 的 CDN 加速功能上补三件事。 ### 1. 加一个「启用 CDN 加速」复选框 当前设计是「CDN 地址留空即关闭」。改成显式开关: - 复选框**未勾** → 功能完全关闭,不管地址和规则填了什么 - 复选框**勾选 + 地址已填** → 生效 - 复选框**勾选 + 地址为空** → **不允许**,保存时要提示「这个必须填」 ### 2. 白名单给一份预制项(写死在主题里) 预制内容(用户指定,13 个后缀): ``` .avif .css .gif .jpeg .jpg .js .json .mp3 .mp4 .pdf .png .svg .webp ``` ### 3. 黑名单也给一份预制项 放「跟安全相关、本来就绝不该走 CDN」的后缀,例如 `.php` 一类。 ### 4. 生效条件(用户原话整理) 1. 两个预制列表**本身不产生任何作用**,只是默认值。 2. 只有**勾了复选框 + 填了 CDN 地址**,预制白名单和预制黑名单才参与匹配。 3. 只勾复选框、没填地址 → 不行,要提示必须填。 ## 设计决定(需确认是否同意) **预制项硬编码在主题代码里,运行时无条件参与匹配;输入框里放的只有用户额外补充的规则,两者叠加。** 理由: 1. **`std` 在运行时完全不起作用** —— Options Framework 的 `std` 只服务「后台预填」和「恢复默认」,`kratos_option()` 取值时压根不看它。所以把预制项写进 `std`,老站点(已保存过配置的)取到的仍然是空值,预制等于不存在。 2. 预制项若写进输入框,用户误删一条就静默失效,且升级时预制列表无法更新。 3. 硬编码之后,用户想**排除**某个预制项,可以在黑名单里写它(黑名单优先),不需要去改输入框。 输入框的说明文字里会列出预制了什么,用户看得见。 ## 写法确认 预制项统一用**带点**写法(`.avif` 而不是 `avif`)。 原因:规则引擎里单个纯字母词会同时按「扩展名」与「路径子串」匹配(这是为了救 `uploads` 那条规则)。`avif` 作子串会命中 `/wp-content/uploads/avif-optimized/a.jpg` 这类路径;带点之后子串是 `.avif`,不会误伤。 ## 验收标准 1. 后台「CDN 加速」页第一个控件是复选框,未勾时前台零变化。 2. 勾选但地址留空,点保存要报错并提示必须填,**配置不被保存**。 3. 勾选 + 填地址后,`.jpg` `.css` 等 13 类资源走 CDN。 4. 预制白名单生效时,`.php` 等不在预制的资源仍保持原地址。 5. 用户在白名单输入框额外写规则,与预制项叠加(不是替换)。 6. 用户在白名单输入框写 `*`,预制黑名单仍然挡住它。 7. 地址清空但保持勾选并存盘,前台零变化(合法状态,只是没生效)。
Author
Owner

收尾:已完成并发布 v3.2.35

提交 adcf80a,已推送 main。更新包与 readme 已发布到主题更新通道,update.json 的 version 已落到 3.2.35。

一、最终实现与建单时的一处差异(已确认后调整)

建单时写的是「预制项硬编码在主题里 + 运行时叠加」。实现前经确认改成了:

预制内容写进白名单/黑名单输入框的默认值(std),用户可以直接改,保存后以用户改的为准,主题不再覆盖。

这个差别很重要,也相应改了实现与验证口径:判据不再是「源码里有这 13 个字符串」,而是「这 13 项真的被预填进了 textarea 的可见内容里」。前者在「硬编码进函数但没进 std」时也是绿的,而那恰好是被否决的方案。

二、三件事怎么落的

1. 「启用 CDN 加速」复选框

  • 位置:CDN 段第一个控件(不是最后)。顺序反了会先让用户填地址、往下滚才看到开关。
  • 不勾时:三个出口全部挡住(should_rewrite / rewrite_html / buffer_start 都过 yang_cdn_active()),前台一个字节都不改,不是「少改一点」。

2. 勾了但地址留空 → 整个保存被拒绝

保存回调返回旧值即可(WP 自己会把旧值写库,结果与没保存等价),并 add_settings_error 提示必须填地址。

这里有一条硬红线:回调里绝不能 update_option() 把旧值写回去 —— 那会在 sanitize_option_kratos 过滤器上递归触发自己,吃爆内存(3.2.11 的事故,报错还会落在区块解析器上,看那个报错会完全找错方向)。

顺带补了一个进页面提示(admin_init):老站点若正卡在「勾着但地址空」的历史状态,一进后台就能看到「功能当前没有生效」。

3. 预制白名单 / 黑名单

白名单 13 项,逐项逐序照需求:

.avif .css .gif .jpeg .jpg .js .json .mp3 .mp4 .pdf .png .svg .webp

黑名单 13 项(安全相关):

.php .php3 .php4 .php5 .phtml .phar .env .sql .bak .log .ini .sh .htaccess

黑名单优先于白名单不变 —— 所以哪怕白名单写成 *,这些后缀也照样不走 CDN。.env 里是数据库密码、.sql 是整库备份,一旦被推到第三方节点缓存上等于公开,源站权限拦不住。

每一项前面都带点(.jpg 而非 jpg):不带点的单词会同时按「扩展名」和「路径子串」匹配,avif 会命中 /uploads/avif-optimized/a.jpg 这种路径。

4. 升级不丢加速

开关的默认值按「CDN 地址是否非空」推算:

  • 老站点已填地址 → 默认勾选 → 升级后行为不变
  • 老站点没填地址 → 默认不勾 → 第一次点保存不会被「必须填地址」拦住

三、过程中顺带修掉的一个真 bug

主机名校验。parse_url 对主机极其宽容,实测:

parse_url('https://not a url at all')  →  host = 'not a url at all'
parse_url('https://exa mple.com/x')    →  host = 'exa mple.com'
parse_url('https://cdn..example.com')  →  host = 'cdn..example.com'

只判 empty($host) 全挡不住。后果不是「少加速一点」,而是全站静态资源一起被拼成畸形地址、站点直接没有样式,而用户在后台看到的只是一个「填了地址」的框。已加主机字符集 / 首尾点 / 连续点 / 子路径空白校验。

四、验证结果

项目 结果
逻辑探针 _cdn335_logic.php 116 / 0
逻辑反向验证 _cdn335_falsify.php 22 / 0
后台真实渲染探针 _admin335_cdn_check.py 74 / 0
后台反向验证 _admin335_falsify.py 23 / 0
包内容契约 _pkgcheck335.py 117 / 0
包契约反向验证 _pkgcheck335_falsify.py 27 / 0
3.2.34 旧探针回归 92 / 0 + 21 / 0(向后兼容)
后台(1360 / 700 两档)几何 四控件可见、不溢出、无大块空白

反向验证里每条注入都必须红在对应的那一条判据上,不是「随便红了就算」。这一轮从中抓出并修掉了 6 处假绿 / 空转判据,其中两处值得一提:

  • checked 判据是假绿:原来在 HTML 串里搜 "checked",但那一段只到 <div id="section-cdn_enable" 就截断了,属性在几十个字符之后的 <input> 上,恒真。已改成量真实的 input.checked。
  • 注释冒充代码:判「本函数里没调 update_option」时,下一个函数上方的注释里正好写着「这里绝对不能调 update_option()」,不剥注释就会误判。已改成先按大括号配平取精确块、再剥注释。

五、部署情况

  • 更新包与 readme 已上线,kratos_yang.zip 的 md5 与本地一致(4ae6eb6c...),下载回来重新解压校验通过。
  • 包内 74 个 PHP 文件在服务器自己的 PHP 上全部 php -l 通过。
  • 按约定没有覆盖服务器上的主题目录:线上仍是 3.2.34 正常运行(前台 58 个资源走 cdn.yangyq.net)。需要更新时请在 WP 后台的「外观 → 主题」里点升级。

六、待你确认

功能本身可用了。以下两点是按合理判断定的,如果和你想的不一样请说一声:

  1. 勾了不填地址是「整单拒绝」(连同同一次里改的其它设置一起作废),不是「只把开关取消」。理由是提交了不合法的表单就不该让其中一部分悄悄生效。
  2. 黑名单除了 .php 系,还放了 .env / .sql / .bak / .log / .ini / .sh / .htaccess。这些不在「改了站点会坏」的硬性排除里,但一旦被推到 CDN 就等于公开。
## 收尾:已完成并发布 v3.2.35 提交 `adcf80a`,已推送 main。更新包与 readme 已发布到主题更新通道,`update.json` 的 version 已落到 `3.2.35`。 ### 一、最终实现与建单时的一处差异(已确认后调整) 建单时写的是「预制项硬编码在主题里 + 运行时叠加」。实现前经确认改成了: > **预制内容写进白名单/黑名单输入框的默认值(`std`),用户可以直接改,保存后以用户改的为准,主题不再覆盖。** 这个差别很重要,也相应改了实现与验证口径:判据不再是「源码里有这 13 个字符串」,而是「这 13 项真的被预填进了 textarea 的可见内容里」。前者在「硬编码进函数但没进 std」时也是绿的,而那恰好是被否决的方案。 ### 二、三件事怎么落的 **1. 「启用 CDN 加速」复选框** - 位置:CDN 段**第一个**控件(不是最后)。顺序反了会先让用户填地址、往下滚才看到开关。 - 不勾时:三个出口全部挡住(`should_rewrite` / `rewrite_html` / `buffer_start` 都过 `yang_cdn_active()`),前台**一个字节都不改**,不是「少改一点」。 **2. 勾了但地址留空 → 整个保存被拒绝** 保存回调返回旧值即可(WP 自己会把旧值写库,结果与没保存等价),并 `add_settings_error` 提示必须填地址。 这里有一条硬红线:**回调里绝不能 `update_option()` 把旧值写回去** —— 那会在 `sanitize_option_kratos` 过滤器上递归触发自己,吃爆内存(3.2.11 的事故,报错还会落在区块解析器上,看那个报错会完全找错方向)。 顺带补了一个进页面提示(`admin_init`):老站点若正卡在「勾着但地址空」的历史状态,一进后台就能看到「功能当前没有生效」。 **3. 预制白名单 / 黑名单** 白名单 13 项,逐项逐序照需求: ``` .avif .css .gif .jpeg .jpg .js .json .mp3 .mp4 .pdf .png .svg .webp ``` 黑名单 13 项(安全相关): ``` .php .php3 .php4 .php5 .phtml .phar .env .sql .bak .log .ini .sh .htaccess ``` 黑名单优先于白名单不变 —— 所以哪怕白名单写成 `*`,这些后缀也照样不走 CDN。`.env` 里是数据库密码、`.sql` 是整库备份,一旦被推到第三方节点缓存上等于公开,源站权限拦不住。 每一项前面都带点(`.jpg` 而非 `jpg`):不带点的单词会同时按「扩展名」和「路径子串」匹配,`avif` 会命中 `/uploads/avif-optimized/a.jpg` 这种路径。 **4. 升级不丢加速** 开关的默认值按「CDN 地址是否非空」推算: - 老站点已填地址 → 默认勾选 → 升级后行为不变 - 老站点没填地址 → 默认不勾 → 第一次点保存不会被「必须填地址」拦住 ### 三、过程中顺带修掉的一个真 bug 主机名校验。`parse_url` 对主机极其宽容,实测: ``` parse_url('https://not a url at all') → host = 'not a url at all' parse_url('https://exa mple.com/x') → host = 'exa mple.com' parse_url('https://cdn..example.com') → host = 'cdn..example.com' ``` 只判 `empty($host)` 全挡不住。后果不是「少加速一点」,而是全站静态资源一起被拼成畸形地址、**站点直接没有样式**,而用户在后台看到的只是一个「填了地址」的框。已加主机字符集 / 首尾点 / 连续点 / 子路径空白校验。 ### 四、验证结果 | 项目 | 结果 | |---|---| | 逻辑探针 `_cdn335_logic.php` | 116 / 0 | | 逻辑反向验证 `_cdn335_falsify.php` | 22 / 0 | | 后台真实渲染探针 `_admin335_cdn_check.py` | 74 / 0 | | 后台反向验证 `_admin335_falsify.py` | 23 / 0 | | 包内容契约 `_pkgcheck335.py` | 117 / 0 | | 包契约反向验证 `_pkgcheck335_falsify.py` | 27 / 0 | | 3.2.34 旧探针回归 | 92 / 0 + 21 / 0(向后兼容) | | 后台(1360 / 700 两档)几何 | 四控件可见、不溢出、无大块空白 | 反向验证里每条注入都**必须红在对应的那一条判据上**,不是「随便红了就算」。这一轮从中抓出并修掉了 6 处假绿 / 空转判据,其中两处值得一提: - **`checked` 判据是假绿**:原来在 HTML 串里搜 `"checked"`,但那一段只到 `<div id="section-cdn_enable"` 就截断了,属性在几十个字符之后的 `<input>` 上,恒真。已改成量真实的 `input.checked`。 - **注释冒充代码**:判「本函数里没调 `update_option`」时,下一个函数上方的注释里正好写着「这里绝对不能调 update_option()」,不剥注释就会误判。已改成先按大括号配平取精确块、再剥注释。 ### 五、部署情况 - 更新包与 readme 已上线,`kratos_yang.zip` 的 md5 与本地一致(`4ae6eb6c...`),下载回来重新解压校验通过。 - 包内 74 个 PHP 文件在服务器自己的 PHP 上全部 `php -l` 通过。 - **按约定没有覆盖服务器上的主题目录**:线上仍是 3.2.34 正常运行(前台 58 个资源走 `cdn.yangyq.net`)。需要更新时请在 WP 后台的「外观 → 主题」里点升级。 ### 六、待你确认 功能本身可用了。以下两点是按合理判断定的,如果和你想的不一样请说一声: 1. **勾了不填地址是「整单拒绝」**(连同同一次里改的其它设置一起作废),不是「只把开关取消」。理由是提交了不合法的表单就不该让其中一部分悄悄生效。 2. **黑名单除了 `.php` 系,还放了 `.env / .sql / .bak / .log / .ini / .sh / .htaccess`**。这些不在「改了站点会坏」的硬性排除里,但一旦被推到 CDN 就等于公开。
Author
Owner

用户确认功能没问题,关单。

最终形态见上一条评论。有一条流程上的补充:按约定没有解包覆盖服务器主题目录,线上跑的是 3.2.34,3.2.35 通过主题更新通道下发,需在 WP 后台「外观 → 主题」点升级才会生效。

用户确认功能没问题,关单。 最终形态见上一条评论。有一条流程上的补充:**按约定没有解包覆盖服务器主题目录**,线上跑的是 3.2.34,3.2.35 通过主题更新通道下发,需在 WP 后台「外观 → 主题」点升级才会生效。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: laoyang/wordpress-kratos-yang#4