DISABLE_WP_CRON = true 并不能封锁 wp-cron.php 端点;它只是停止了 WordPress 发起自身的环回请求(loopback request)。该文件在 Web 端仍然是可访问的,因此任何人仍然可以访问它并强制执行完整的 WordPress 引导(bootstrap)过程。

这个隐藏的入口点会浪费 CPU、内存和 PHP 工作进程(workers),在访问量大的网站上尤其如此。如果你以为你已经关上了这扇门,其实还没有。

为什么该设置经常被误解

当 WordPress 运行计划任务时,它首先会尝试向自身的 wp-cron.php 文件发送一个快速的 HTTP 请求。将 DISABLE_WP_CRON 设置为 true 是告诉核心跳过该内部请求。核心不会更改 Web 服务器配置,也不会为 wp-cron.php 添加任何身份验证层。即使 PHP 进程提前中止,该脚本仍然是一个返回 200 状态码的公开 URL。

发现该 URL 的攻击者可以反复对其进行 ping 操作,导致 WordPress 每次都要加载所有插件、主题和数据库。在共享主机或 PHP 工作进程有限的网站上,这单个端点可能会变成拒绝服务(DoS)攻击的向量。

真正需要做的是什么

要将计划任务转移到系统级调度器(cron、systemd-timer 等)并关闭公开入口,请遵循以下五个步骤。

1. 禁用内部环回

wp-config.php 中添加以下行:

define( 'DISABLE_WP_CRON', true );

这会停止 WordPress 尝试其自身的 HTTP 请求,但不会停止外部调用。

2. 在 Web 服务器端拦截 wp-cron.php

以 Nginx 为例,插入一个返回 403 Forbidden 的 location 块:

location = /wp-cron.php {
    return 403;
}

现在,服务器会在 PHP 启动之前就拒绝请求,从而消除了引导成本。

3. 添加 mu-plugin 作为安全网

创建一个必须使用插件(placed in wp-content/mu-plugins),用于记录任何到达 wp-cron.php 的请求并以 403 状态退出。这可以捕获那些以某种方式绕过服务器规则的请求——例如通过不同的主机名或 CDN 边缘规则。

4. 抑制 Action Scheduler 的异步调用

许多插件使用 Action Scheduler 库,它可能会产生自身的环回请求。通过挂载到 action_scheduler_queue_runner 并对非 CLI 请求提前返回,可以防止该库尝试打开自己的入口。

5. 从 WP-Cron 钩子中解除队列运行器的挂载

移除附加到 wp cron 钩子的默认 Action Scheduler 队列运行器。这确保了队列仅在您通过命令行显式触发时才运行。

正确运行任务

在公开端点被封锁后,使用系统调度器通过 WP-CLI 每分钟(或您需要的任何频率)调用一次 WordPress:

wp cron event run --due-now

该单一命令会在受控环境中处理核心 cron 事件 Action Scheduler 队列,并使用与任何其他 CLI 任务相同的 PHP 进程。

可衡量的收益

  • 安全性 – 任何未经身份验证的用户都无法启动沉重的后台任务。
  • 性能 – PHP 工作进程可以留给真实的访客;因随机 cron 请求导致的内存峰值将消失。
  • 可靠性 – 任务调度变得具有主动性;您确切知道任务何时运行,因为它是由系统的 cron 驱动的,而不是由访客的页面加载驱动的。

变更后需要注意什么

不要依赖 wp-cron.php 的 HTTP 状态码;即使被 PHP 拦截,它仍可能返回 200。相反,你应该:

  • 监控 Action Scheduler 的队列大小。队列不断增长通常意味着任务运行失败。
  • 检查服务器日志中来自 wp-cron.php location 块的 “403” 条目。
  • 在流量高峰期间观察 PHP-FPM 或 FastCGI 进程数,以确认负载是否下降。

注意事项

一些管理员将 DISABLE_WP_CRON 保持为 false,因为他们依赖低流量网站自然触发 cron。上述方法完全消除了这种依赖,但也增加了一个维护步骤:您必须确保系统调度器可靠运行。如果服务器的 cron 守护进程失效,计划任务就会停止。请务必配合对系统 cron 服务的监控,以避免这一隐患。

总结:DISABLE_WP_CRON 设置为 true 仅停止 WordPress 自行 ping 自己;它并不会关闭公开的 wp-cron.php 端点。请在 Web 服务器端拦截该文件,添加 mu-plugin 作为后备,并通过 WP-CLI 将所有计划任务路由到系统调度器。这样做可以保护网站安全,减少不必要的 PHP 工作,并让您精确控制后台任务的执行时间。