用 AI 搭一个应用棒极了——直到你把它毫无防护地发布到网上。而这恰恰是整条路上最危险的时刻:AI 处于建造者模式,它专注于让应用「跑起来」,而不是它会怎样被攻击。结果就是:一个个漂亮的应用里,任何人只要改一改 URL 里的一个数字,就能看到另一个用户的数据;API 可以被全世界任何一个网站调用;浏览器也没有收到任何防御指令。本指南覆盖最常被遗忘的 3 把锁——RLS、CORS 和安全 headers——每一把都配一个比喻、真实的风险,以及一段你可以直接甩给 AI、让它替你配置好的详细提示词。你不需要懂它内部是怎么运作的:只要知道每样东西叫什么名字、什么时候该用它就够了。
时机很清楚,也没得商量:就在你发布应用、或把它交给真实用户之前。 当你只是一个人在自己电脑上测试时,什么都不会发生。但在你的应用连上互联网、装着别人数据的那一秒,没有这几把锁,你就是把一切都暴露了出去。而由于 AI 不会自己去做这件事(它想的是让应用能跑,而不是保护它),所以得由你明确地提出要求。
没有 RLS,一个恶意用户只需要在 URL 或一个请求里改一改某个 ID,就能看到另一个人的数据。这是在使用 Supabase 和 PostgreSQL 的应用里最常见的漏洞——也是最容易被利用的。这就是为什么它是第 1 把锁。
我在用 Supabase 搭配 PostgreSQL。我有这些表:[列出你的表和它们的用户列,例如:posts (user_id)、comments (post_id, user_id)]。 请配置 Row-Level Security,让每个用户只能查看/编辑/删除属于自己的记录。请遵循 Supabase 的官方最佳实践: - 在所有表上启用 RLS(ENABLE ROW LEVEL SECURITY)。 - 为 SELECT、INSERT、UPDATE 和 DELETE 分别创建独立的策略(不要用 FOR ALL)。 - 对性能很重要:把用户函数包装成 (SELECT auth.uid()),而不是裸用 auth.uid(),这样 Postgres 每次查询只求值一次,而不是每行求值一次。 - 把策略限制到 authenticated 角色(TO authenticated),而不是 public,这样匿名访客根本碰不到这张表。 - 绝对不要在策略里用 user_metadata(用户可以修改它)。 - 在策略用到的列上加索引(例如 user_id)。 - 记住:要让 UPDATE 生效,还需要一个 SELECT 策略。 - 给我完整的、可以直接贴到 Supabase SQL Editor 里的 SQL,并用一行话解释每个策略做什么。
auth.uid()。但这会让 Postgres 每一行都求值一次——在一张 100.000 行的表里,差别就是一次 5 毫秒的查询和一次足足 5 秒的查询之间的差距!技巧(由 Supabase 官方文档记载)是:把它写成 `(SELECT auth.uid())`。这样它只会求值一次。这就是为什么上面的提示词里明确地要求了这一点。请在我的后端配置 CORS,让**只有**我的生产域名(https://mi-app.com)和开发环境的 localhost 能够发起请求。 - 生产环境中不要用 "*" 作为允许的来源。 - 只允许我真正用到的方法(例如 GET、POST、PUT、DELETE)。 - 只允许我需要的请求头。 - 根据我的技术栈准确告诉我每样东西该放在哪里:[告诉它你的框架/后端]。
Access-Control-Allow-Origin: *。这就像敞着门,还挂了块牌子写着「请进,钥匙我留在里面了」。如果你的 AI 为了「让它快点跑起来」给你这样配置了,在发布前把它改掉。请给我的应用添加推荐的安全 headers:Content-Security-Policy、X-Frame-Options、X-Content-Type-Options、Referrer-Policy、Strict-Transport-Security (HSTS) 和 Permissions-Policy。 - 用一行简单的话解释每一个是做什么的。 - 给我针对我的框架、可以直接用的配置:[告诉它你用哪个,例如 Next.js、Express]。 - 先以 report-only 模式启动 Content-Security-Policy,这样不会弄坏任何东西,再告诉我之后怎么把它收紧。 - 告诉我怎么验证结果。
*。Join 4,200+ builders. No credit card. Build your first app with AI in minutes.