frankenphp 不改变 wordpress 版本输出逻辑,但因默认静态文件直出(如 /wp-includes/ 下资源),导致 remove_action('wp_head', 'wp_generator') 对 js/css 中 ?ver= 无效;需同时在 php 层过滤动态输出、在 caddyfile 或 frankenphp.yaml 中重写 url 剥离 ?ver=,并清理 readme.html、rss、rest api 等隐蔽出口。

直接说结论:FrankenPHP 本身不改变 WordPress 版本信息的输出逻辑,藏版本号的关键动作和传统 PHP-FPM 环境完全一致,但必须额外检查 FrankenPHP 的静态文件服务行为是否绕过 WordPress 的 functions.php 过滤。
为什么 FrankenPHP 下 remove_action('wp_head', 'wp_generator') 有时失效
FrankenPHP 默认启用「静态文件直出」(如 /wp-includes/js/wp-embed.min.js?ver=6.5.1),这类请求不经过 PHP 解析,script_loader_src 过滤器根本不会触发。结果就是:HTML 中的 <meta name="generator"> 被清掉了,但 JS/CSS 文件 URL 里的 ?ver=6.5.1 依然明晃晃挂着。
常见错误现象:
- 源码里看不到 <meta name="generator">
- 但用浏览器开发者工具 Network 面板一查,所有 .js 和 .css 请求仍带完整版本参数
- WPScan 或类似扫描器仍能准确识别出 WordPress 版本
- 必须同时处理 PHP 动态输出(
wp_head、the_generator)和静态资源路径(style_loader_src/script_loader_src) - FrankenPHP 的
static_files配置若设为true(默认),则/wp-includes/下资源走直出,add_filter失效 - 验证方法:访问一个带
?ver=的 JS 文件 URL,看响应头是否含X-Powered-By: FrankenPHP—— 若有,说明是 FrankenPHP 直出,PHP 层过滤未生效
彻底清除 ?ver= 参数的两种可行路径
不能只靠 PHP 过滤,得从源头切断或重写。推荐以下组合:
- 在主题
functions.php中保留标准过滤,覆盖动态生成场景:remove_action('wp_head', 'wp_generator');add_filter('the_generator', '__return_empty_string');add_filter('style_loader_src', 'remove_wp_version_strings', 9999);add_filter('script_loader_src', 'remove_wp_version_strings', 9999); - 在 FrankenPHP 的
Caddyfile或frankenphp.yaml中添加重写规则,强制剥离所有?ver=:rewrite * { if {query} contains "ver=" strip_prefix "ver={.*}" }(Caddy v2.8+ 语法)
或更稳妥的正则替换:uri replace "(\?.*)?ver=[^&]*" "{1}" - 删除根目录
readme.html—— 这个文件 FrankenPHP 会原样返回,且含明确版本字符串,必须手动删
别漏掉 RSS 和 REST API 这两个隐蔽出口
攻击者常通过 /feed 或 /wp-json/ 提取版本号,FrankenPHP 不干预这些端点,WordPress 默认仍会暴露:
-
/feed响应中<generator>https://wordpress.org/?v=6.5.1</generator>—— 加这行:add_filter('get_the_generator_html', '__return_false');add_filter('get_the_generator_xhtml', '__return_false'); -
/wp-json/响应头含X-WP-Total: 6.5.1(部分版本)—— 无法用 filter 清除,只能用 FrankenPHP 的响应头重写:header -X-WP-Total(Caddy)或headers: { -X-WP-Total }(frankenphp.yaml) - 检查
/wp-json/wp/v2/posts返回的_links.self.href是否含wp-json/wp/v2/—— 这个无法隐藏,但至少确保它不带版本号参数
最易被忽略的一点:FrankenPHP 启动时若加载了旧版 WordPress 的 wp-config.php,而该配置里有 define('WP_CONTENT_DIR', ...) 等路径硬编码,可能导致某些插件绕过主题 functions.php 的过滤逻辑。动手前先确认 wp-config.php 里没残留的版本相关常量或钩子注册。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











