WordPress 被黑了?迁移到 Next.js + Supabase 是你最好的解决方案
我已经数不清有多少次客户带着同样的故事找到我们:"我们的 WordPress 网站被黑了。我们清理了它。它又被黑了。我们放弃了。" 最近的一个是一家中等规模电商公司,他们的 WooCommerce 商店被注入了信用卡窃取程序,隐藏在看似合法的插件更新中。他们泄露了客户支付数据三周才被发现。这不是边界情况。这就是 2026 年 WordPress 生态系统的日常。
本文并不是在抨击 WordPress。它之所以能够支撑网络的很大一部分是有原因的。但是让它在 2005 年可访问的架构,正是让它在 2026 年成为自动化攻击磁石的原因。如果你已经被黑过——或者你已经厌倦了在安全插件上花钱,而这些插件本身就是攻击向量——这是你迁移到更安全系统的行动手册。
目录
- WordPress 安全问题的架构根源
- 2026 年常见的 WordPress 攻击向量
- 无头架构为什么能消除整个类别的攻击
- Next.js + Supabase:安全优先的技术栈
- 攻击面对比:WordPress vs 无头架构
- 迁移手册:WordPress 到 Next.js + Supabase
- 迁移后的安全加固
- WordPress 安全与迁移的真实成本
- 常见问题

WordPress 安全问题的架构根源
让我明确说一点:WordPress 核心团队做了扎实的安全工作。WordPress 核心,保持更新,是相当安全的。但没有人只是运行 WordPress 核心。平均的 WordPress 网站安装了 20-30 个插件。每一个都是你没有写的依赖,由你不认识的人维护,可以访问你的数据库、文件系统和用户数据。
这是在"WordPress 安全最佳实践"文章中经常被忽略的关键点:问题不在于 WordPress 网站所有者疏忽。问题在于 WordPress 的架构要求你直接在服务器上安装来自第三方的可执行 PHP 代码来获得基本功能。这相当于给每一个在你家工作的承包商永久复制你的房钥匙。
WPScan 的漏洞数据库在 2024 年追踪了超过 7,900 个新的 WordPress 漏洞,其中大约 96% 来自插件。Sucuri 的 2024 年威胁报告发现,WordPress 占他们清理的所有 CMS 感染的大约 95%。Patchstack 报告称,2024 年 33% 的严重 WordPress 漏洞在披露时没有补丁可用。
这些不是可以通过更好的编码实践修复的错误。它们是架构本身的涌现特性。
2026 年常见的 WordPress 攻击向量
在我们谈论修复之前,让我们列举一下你实际上在防御什么。我个人已经审查过数十个被攻破的 WordPress 网站,攻击遵循可预测的模式。
通过插件的 SQL 注入
WordPress 使用具有文档良好的架构的 MySQL 数据库。每个接受用户输入并接触数据库的插件都是潜在的 SQL 注入点。$wpdb->prepare() 函数存在,但它是可选的。插件开发者忘记了它、误用了它,或者对"简单"查询完全跳过了它。
我曾经追踪过一个注入,它来自一个已被放弃 18 个月但仍安装在 200,000+ 网站上的联系表单插件。攻击者使用基于 UNION 的注入来转储 wp_users 表,获取管理员密码哈希,并在离线状态下破解弱密码。
-- 典型的 WordPress SQL 注入在日志中的样子
GET /wp-content/plugins/vulnerable-plugin/ajax.php?id=1%20UNION%20SELECT%201,user_login,user_pass,4,5%20FROM%20wp_users--
PHP 对象注入和远程代码执行
WordPress 对 serialize() 和 unserialize() 的大量使用为 PHP 对象注入创造了机会。当插件反序列化用户控制的数据(许多都这样做)时,攻击者可以制作在反序列化过程中执行任意代码的有效负载。
在 2024 年,一个流行备份插件(安装在 500 万+ 网站上)的严重 RCE 漏洞允许未经身份验证的攻击者执行任意 PHP 代码。修复花了 11 天才发布。11 天内,每个运行该插件的网站都是待宰的羔羊。
插件供应链攻击
这是最让我害怕的。攻击者购买有大量安装基础的被放弃插件,推送包含后门的"安全更新",WordPress 自动更新机制将恶意软件分发给每个运行该插件的网站。它发生在 Display Widgets(300,000 个安装)和 Social Warfare(70,000 个安装)上,这些只是被捉住的。
对 wp-login.php 的暴力破解攻击
每个 WordPress 网站默认暴露 /wp-login.php 和 /xmlrpc.php。自动僵尸网络不断袭击这些端点。Wordfence 报告称,2024 年他们网络中平均每月阻止了 30 亿次恶意请求。即使有速率限制和双因素认证,你也在花费服务器资源处理这些攻击。
通过主题和插件的跨站脚本 (XSS)
存储型 XSS 在 WordPress 中特别危险,因为管理员仪表板和公共网站共享相同的会话上下文。通过评论、表单提交或易受攻击的插件设置注入的 XSS 有效负载可以升级为完全的管理员访问权限。
无头架构为什么能消除整个类别的攻击
现在事情变得有趣了。无头架构不仅可以减少你的攻击面——它通过移除使攻击成为可能的条件来消除整个类别的攻击。
在传统的 WordPress 设置中,呈现 HTML 的同一服务器也:
- 运行来自 20+ 第三方插件的 PHP 代码
- 管理用户身份验证
- 连接到数据库
- 提供管理员界面
- 处理文件上传
- 处理表单提交
这对单个应用来说是很多责任。在使用 Next.js 和 Supabase 的无头设置中,这些责任被分散到隔离的服务中:
- 前端(Next.js 在 Vercel/Netlify): 从 CDN 提供的静态 HTML/JS。在大多数情况下,没有向公网暴露的服务器端运行时。
- 数据库 + 身份验证(Supabase): 带有行级安全的托管 Postgres,永远不会直接暴露给最终用户。
- API 层: 具有明确、最小端点的无服务器函数。
- CMS(如果需要): 在自己隔离的基础设施上运行的无头 CMS。
没有 PHP 可以注入。没有具有写入权限的插件目录。没有在管理员和公共网站之间的共享会话。没有 wp-login.php 供机器人猛击。
你不需要 WAF 来保护一个不存在的攻击面。

Next.js + Supabase:安全优先的技术栈
让我们具体说说为什么这个特定的组合从安全角度来说效果这么好。
Next.js:不运行代码的前端
当你用静态生成 (SSG) 或增量静态再生 (ISR) 构建 Next.js 网站时,部署的是 CDN 上的 HTML、CSS 和 JavaScript 文件。没有应用服务器实时处理请求。你不能 SQL 注入一个 CDN。
对于动态功能,Next.js 服务器操作和路由处理程序作为无服务器函数运行。每个函数是:
- 在自己的执行上下文中隔离的
- 无状态的(请求之间没有共享内存)
- 短期的(冷启动、执行、终止)
- 明确定义的(没有端点的自动发现)
// Next.js 路由处理程序 -- 明确、有类型、最小化
import { createClient } from '@/lib/supabase/server'
import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
const ContactSchema = z.object({
name: z.string().min(1).max(100),
email: z.string().email(),
message: z.string().min(10).max(5000),
})
export async function POST(request: NextRequest) {
const body = await request.json()
const parsed = ContactSchema.safeParse(body)
if (!parsed.success) {
return NextResponse.json({ error: 'Invalid input' }, { status: 400 })
}
const supabase = await createClient()
const { error } = await supabase
.from('contact_submissions')
.insert(parsed.data)
if (error) {
return NextResponse.json({ error: 'Submission failed' }, { status: 500 })
}
return NextResponse.json({ success: true })
}
将其与必须钩入 WordPress 的操作系统、包含自己的 AJAX 处理程序、管理自己的 nonce 验证和构建自己的 SQL 查询的 WordPress 联系表单插件进行比较。Next.js 版本有更少的移动部分,通过 Zod 验证输入,以及通过 Supabase 客户端的参数化查询。
Supabase:带行级安全的 Postgres
Supabase 为你提供了一个托管的 PostgreSQL 数据库,带有一个杀手级功能:行级安全 (RLS)。与其相信你的应用代码来强制执行访问控制(WordPress 模型),你定义数据库级别的安全策略。
-- 只有经过身份验证的用户可以读他们自己的数据
CREATE POLICY "Users can view own profile"
ON profiles
FOR SELECT
USING (auth.uid() = user_id);
-- 公共可以插入到联系提交但不能读
CREATE POLICY "Anyone can submit contact form"
ON contact_submissions
FOR INSERT
WITH CHECK (true);
CREATE POLICY "Only admins can read submissions"
ON contact_submissions
FOR SELECT
USING (auth.jwt() ->> 'role' = 'admin');
即使攻击者找到了一种方式来进行任意 Supabase 查询(在没有 PHP 执行上下文的情况下已经困难得多),RLS 策略也会阻止他们访问他们不应该看到的数据。这是深度防御,WordPress 从根本上无法提供,因为它的权限系统是在 PHP 代码中实现的,而不是在数据库层。
Supabase 还通过对电子邮件/密码、魔法链接、OAuth 提供商和多因素身份验证的内置支持来处理身份验证。不需要插件。没有第三方代码在你的服务器上运行。
攻击面对比:WordPress vs 无头架构
让我们并排放置这个。
| 攻击向量 | WordPress | Next.js + Supabase |
|---|---|---|
| SQL 注入 | 高风险 -- 插件构建原始查询 | 接近零 -- 通过 Supabase 客户端参数化查询,RLS 作为备份 |
| PHP/远程代码执行 | 高风险 -- 插件执行服务器端 PHP | 不适用 -- 没有 PHP 运行时 |
| 插件供应链 | 严重风险 -- 自动更新分发恶意软件 | 不适用 -- 没有插件生态系统 |
| 暴力破解(登录) | 总是暴露(wp-login.php、xmlrpc.php) |
通过 Supabase Auth 或单独仪表板的管理员访问,不需要公共登录端点 |
| XSS(存储型) | 高风险 -- 共享管理员/公开上下文 | 低风险 -- React 默认转义输出,管理员和公共是单独的应用 |
| 文件上传利用 | 高风险 -- 上传的 PHP 文件可以执行 | 低风险 -- 上传到对象存储(Supabase Storage/S3),永远不会作为代码执行 |
| 数据库暴露 | 如果服务器受到破坏,直接 MySQL 访问 | 数据库在 Supabase 基础设施后面,RLS 策略作为最后的防线 |
| DDoS 源 | 服务器必须处理每个请求 | CDN 上的静态资产,很少打到源 |
| 已知路径枚举 | wp-admin、wp-content、wp-includes 都是可扫描的 |
没有可预测的路径,没有暴露的管理路由 |
迁移手册:WordPress 到 Next.js + Supabase
好的,你被说服了(或你被黑的网站说服了你)。这是实际如何做的。我们已经进行了足够多的这种迁移,有一个可重复的过程。
阶段 1:审查和内容审计(第 1 周)
在你接触任何代码之前,你需要了解你实际上拥有什么。
- 导出所有 WordPress 内容使用 WP-CLI 或 REST API。不要依赖 XML 导出——它们缺少元字段和自定义文章类型。
- 列出所有插件提供的功能。制作电子表格:插件名称、它做什么、你是否真的需要它,以及什么替代它。
- 映射 URL 结构为了 SEO 保护。每个现有 URL 都需要一个重定向或在 Next.js 中的匹配路由。
- 识别动态功能 -- 表单、搜索、用户帐户、电商 -- 需要 API 端点。
# 通过 REST API 导出 WordPress 内容
curl -s "https://yoursite.com/wp-json/wp/v2/posts?per_page=100&page=1" | jq '.' > posts_page1.json
curl -s "https://yoursite.com/wp-json/wp/v2/pages?per_page=100" | jq '.' > pages.json
curl -s "https://yoursite.com/wp-json/wp/v2/media?per_page=100" | jq '.' > media.json
阶段 2:Supabase 架构和数据迁移(第 2 周)
基于内容审计设计你的 Supabase 数据库架构。不要只是复制 WordPress 架构——它充满了元数据表和序列化数据块。
-- 干净、专用的架构
CREATE TABLE posts (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
title TEXT NOT NULL,
slug TEXT UNIQUE NOT NULL,
content TEXT,
excerpt TEXT,
featured_image TEXT,
status TEXT DEFAULT 'draft' CHECK (status IN ('draft', 'published', 'archived')),
published_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
author_id UUID REFERENCES auth.users(id)
);
-- 立即启用 RLS
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Published posts are public"
ON posts FOR SELECT
USING (status = 'published');
CREATE POLICY "Authors can manage own posts"
ON posts FOR ALL
USING (auth.uid() = author_id);
写一个迁移脚本(Node.js 或 Python),将 WordPress JSON 导出转换为你的新架构,并将它们插入到 Supabase。
阶段 3:Next.js 构建(第 3-5 周)
构建你的 Next.js 前端。如果你正在与熟悉该技术栈的团队合作,这进展很快。如果你需要帮助,我们的 Next.js 开发团队已经进行过足够多次这种迁移,对正确的模式有强烈的看法。
关键的架构决策:
- 内容页面的静态生成 -- 博客文章、登陆页面、关于页面。这些成为 CDN 上的 HTML 文件。
- 动态数据的服务器组件 -- 在请求时从 Supabase 获取,带缓存。
- 表单提交的路由处理程序 -- 联系表单、通讯注册等。
- 重定向的中间件 -- 处理所有旧的 WordPress URL。
// next.config.ts -- 处理 WordPress URL 重定向
const nextConfig = {
async redirects() {
return [
{
source: '/category/:slug',
destination: '/blog/category/:slug',
permanent: true,
},
{
source: '/:year(\\d{4})/:month(\\d{2})/:slug',
destination: '/blog/:slug',
permanent: true,
},
// wp-login.php -- 发送机器人到一个 410
{
source: '/wp-login.php',
destination: '/gone',
permanent: true,
},
{
source: '/wp-admin/:path*',
destination: '/gone',
permanent: true,
},
]
},
}
阶段 4:测试和 SEO 验证(第 6 周)
- 针对新网站运行 Screaming Frog,验证每个旧 URL 要么解析要么重定向。
- 验证结构化数据(JSON-LD)存在于所有页面上。
- 测试所有表单和动态功能。
- 运行 Lighthouse 和 Core Web Vitals 检查 -- 你几乎肯定会看到改进,因为你现在从 CDN 提供。
- 用 Vercel Analytics 或你喜欢的工具设置监控。
阶段 5:启动和 DNS 切换(第 6-7 周)
部署到 Vercel 或 Netlify,更新 DNS,并设置监控。保持旧 WordPress 实例离线但可访问 30 天,以防你需要参考任何内容。
如果你的网站有重大流量或电商功能,考虑一个无头 CMS 集成用于内容管理,并与我们讨论将 Astro 作为替代前端,用于内容丰富的网站,其中构建性能很重要。
迁移后的安全加固
一旦你在新的技术栈上,这里是你的安全检查清单:
- 在每个表上启用 Supabase RLS。 没有例外。如果表没有策略,它要么是无法访问的(好默认),要么是完全开放的(不好)。
- 为所有秘密使用环境变量。 Vercel 和 Netlify 都处理得很好。永远不要提交 API 密钥。
- 设置 Supabase 数据库备份。 时间点恢复在专业计划上可用($25/月)。
- 在你的 Next.js 中间件中配置内容安全策略头。
- 启用 Vercel 的 DDoS 保护(包含在所有计划中)。
- 设置正常运行时间监控 -- 我们使用 Better Uptime,但 Checkly 和 Vercel 的内置监控也行。
- 季度审计你的 Supabase RLS 策略。 使用 Supabase 的 SQL 编辑器用不同的用户上下文测试策略。
// middleware.ts -- 安全头
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const response = NextResponse.next()
response.headers.set('X-Frame-Options', 'DENY')
response.headers.set('X-Content-Type-Options', 'nosniff')
response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')
response.headers.set(
'Content-Security-Policy',
"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';"
)
response.headers.set(
'Permissions-Policy',
'camera=(), microphone=(), geolocation=()'
)
return response
}
WordPress 安全与迁移的真实成本
让我们谈钱,因为那是真正驱动决策的。
| 成本类别 | WordPress(年度) | Next.js + Supabase(年度) |
|---|---|---|
| 托管 | $300-1,200(托管 WP) | $0-240(Vercel Pro) |
| 安全插件(Wordfence/Sucuri) | $200-500 | $0(不需要) |
| SSL/CDN | $0-200 | $0(包含) |
| 恶意软件清理(如果被黑) | 每次事件 $500-2,500 | 不适用 |
| 开发人员在安全补丁上的时间 | $2,000-5,000 | $500-1,000 |
| 数据库(Supabase) | 包含在托管中 | $0-300(免费层到专业版) |
| 总计 | $3,000-9,400 | $500-1,540 |
这还没有考虑停机时间、失去客户信任的成本,以及如果客户数据被破坏可能的监管罚款。单一的 GDPR 可报告的违规可能会导致数万美元的法律和合规开销。
迁移本身通常花费 $10,000-40,000,取决于网站的复杂性。对于大多数企业,这在 1-2 年内就能通过减少安全支出而收回——你还能获得更快、更易维护的网站。查看我们的定价页面了解迁移项目的具体情况。
常见问题
WordPress 真的那么不安全,还是这被夸大了? WordPress 核心得到了良好的维护。问题在于几乎没有人只运行核心。插件生态系统是 96% 漏洞的所在地,你无法运行一个有用的 WordPress 网站而不使用插件。这没有被夸大——Sucuri 在 2024 年清理了超过 60,000 个 WordPress 网站的恶意软件。该架构要求你信任第三方 PHP 代码在你的服务器上,这种信任不断被利用。
我不能只是使用更好的安全插件而不迁移吗? 安全插件本身就是在你的服务器上运行的 PHP 代码,具有深度系统访问权限。Wordfence 和 Sucuri 得到了很好的维护,但它们是对架构问题的创可贴。他们还增加了服务器负载,可能与其他插件冲突,并且多年来有自己的漏洞。你在添加复杂性来解决复杂性问题。
WordPress 到 Next.js 的迁移通常需要多长时间? 对于标准商业网站(10-50 页、博客、联系表单),我们通常在 5-7 周内完成迁移。带有 WooCommerce 的电商网站更复杂,取决于产品目录大小和自定义功能,可以花费 8-14 周。如果你有一个更简单的网站,联系我们,我们可以给你一个更具体的时间表。
从 WordPress 迁移到新网站时,我会失去 SEO 排名吗? 不会,如果你做得对的话。关键步骤是:保留所有 URL 结构或设置适当的 301 重定向、维护你的结构化数据标记、保持内容完整,并向 Google Search Console 提交更新的站点地图。我们大多数迁移客户在 2-3 个月内看到排名改进,因为当你迁移到由 CDN 提供的静态网站时,Core Web Vitals 分数会大幅提高。
内容编辑怎么办?WordPress 对非技术用户来说很容易。 这是一个合理的问题。你有选项:带有自定义管理仪表板的 Supabase,或像 Sanity、Contentful 或 Payload CMS 这样的无头 CMS,为内容编辑者提供类似于 WordPress 的可视化编辑体验。我们定期处理无头 CMS 集成,并可以推荐适合你团队需求的方案。
Supabase 对生产使用足够安全吗? Supabase 在 AWS 基础设施上运行,具有 SOC 2 Type II 合规性。底层数据库是 PostgreSQL,具有强大的安全跟踪记录。行级安全策略在数据库级别强制执行访问控制,这实际上比 WordPress 的基于 PHP 的权限系统更安全。Supabase 还在付费计划上提供时间点恢复、加密连接和网络限制。
如果我的 WordPress 网站被黑了,我需要立即帮助怎么办? 首先,立即将网站脱机以停止进一步的损害和数据泄漏。其次,保留取证证据(数据库转储、访问日志、文件系统快照)。第三,不要只是清理它并放回去——你可能在几周内被重新感染。使用该事件作为迁移的催化剂。联系我们团队,我们可以帮助进行紧急分类和迁移规划。
我可以一次迁移所有内容,还是可以逐步迁移? 增量迁移是可能的,但增加了复杂性。你可以运行 Next.js 作为前端,同时保持 WordPress 作为无头 CMS 后端暂时,然后完全逐步停止 WordPress。但是,这意味着 WordPress 仍在运行,并且在过渡期间仍需要安全维护。对于大多数网站,干净的切换更快、更便宜,并且更快地消除安全风险。