Tori TIC

你在 Lovable、Bolt、v0 或 Cursor 中构建了一个应用。它在预览中运行完美。你部署了它,打开了在线 URL,现在屏幕一半是空的,或者你看到类似:

permission denied for table profiles
code: 42501

Enter fullscreen mode Exit fullscreen mode

或者你的数据加载为 null,控制台显示 getUser() 返回空值。令人沮丧的是,在正常工作的预览和出现问题的部署之间,你的代码没有任何变化。那么发生了什么?

为什么这几乎发生在每个 AI 构建的应用中

这是我们看到的最常见故障之一,而且这不是随机的。AI 应用构建器能快速生成一个可用的前端,但它们通常会让你的应用与数据库之间的安全边界半途而废。通常同时存在以下两点:

  1. 行级安全(RLS)已开启。Supabase 启用了 RLS,因此只有正确的用户才能读取或写入表。这是正确的,你也需要它。你的策略可能类似于“当 auth.uid() = user_id 时,行可见”。

  2. 在生产环境中到达 Supabase 的请求是匿名的。在构建器预览中,请求通常携带了你的会话,或以提升的权限运行,因此 RLS 允许通过。而在真正的部署中,服务器在调用 Supabase 时没有附加已登录用户的身份。所以 auth.uid() 为 null,策略不匹配,Supabase 正确地以 42501 permission denied 拒绝。

简单来说:你的安全规则正在工作,但你的应用在敲门时没有出示自己的身份。

如何确认这是你的问题

在更改任何内容之前,请保留确切的错误文本。然后按顺序检查:

  • 失败的表是否启用了 RLS?在 Supabase 中,打开该表并查看其策略。如果 RLS 已开启且没有与你的查询匹配的策略,则每次读取或写入都会失败。
  • 服务器上的请求是否已认证?在运行查询的服务器路由上添加日志,并打印它是否包含用户。如果它打印 null 或 anonymous,那就是原因。
  • 你的环境变量是否指向失败的同一个 Supabase 项目?部署指向错误的项目,或缺少 SUPABASE_URL 和 anon key,会产生相同的症状。
  • 你的身份验证重定向 URL 是否包含在线域名?在 Supabase Auth 设置中,站点 URL 和重定向允许列表必须包含你的生产域名,而不仅仅是 localhost。

修复方法

真正的修复方法是让请求携带用户的身份,以便在 RLS 检查时 auth.uid() 被填充。在 Next.js 和 Supabase 应用中,这通常意味着:

  1. 在任何触及受保护表的服务器路由或操作上,使用请求范围的服务器客户端读取身份验证 cookie,而不是使用普通的匿名客户端。
  2. 在中间件中刷新会话,以便在导航过程中以及在生产域上硬刷新后,cookie 保持有效。
  3. 确认 RLS 策略与你的实际访问模式匹配。如果用户应该看到自己的行,则策略会将 auth.uid() 与行的用户列进行比较。不要通过关闭 RLS 来“修复”这个问题。
  4. 将生产域名添加到 Supabase Auth 重定向 URL,然后重新测试完整路径:在在线 URL 上登录、加载页面并硬刷新。

然后重新运行导致失败的确切用户操作,并确认它在相同的 Supabase 项目和域名上正常工作。

注意事项

诱人的捷径是禁用 RLS 或在浏览器中使用服务角色密钥,以便错误消失。请不要这样做。禁用 RLS 会使该表中的每一行对互联网上的任何人可读写,而将服务角色密钥放入客户端代码则会将对数据库的完全控制权交给陌生人。这个错误很烦人,但它正在保护你。

如果你卡住了,或者你不是技术人员

如果你是非技术人员,而这读起来像另一种语言,那很正常。这正是 AI 构建器无法为你完成的那类事情,因为它存在于身份验证、数据库和部署之间的边界。

我们为此运行一项名为 Vibe-Code Rescue 的服务。你粘贴错误即可获得免费的、通俗易懂的诊断,说明问题所在以及修复所需的步骤。如果你希望修复,它是固定费率,你只需在修复验证通过后支付,并且你将拥有自己拥有的干净代码。没有订阅,没有保留金。

免费诊断在这里:https://rescue.ticassociation.com

A TIC Association creation.