⚠️ Alpha内测版本警告:此为早期内部构建版本,尚不完整且可能存在错误,欢迎大家提Issue反馈问题或建议
Skip to content

8.4 安全检查与问题排查

本节目标:建立安全开发的阶段意识,遇到问题时能快速定位和解决。


安全清单

小明经历了密钥泄露、管理后台被闯入、CORS 报错之后,问老师傅:"有没有一个清单,让我每次开发时对着检查,不要再踩坑了?"

老师傅说:"有。安全不是上线前突击检查一次就完事的,它贯穿整个开发周期——从创建项目的第一秒开始。"

开发前——地基要打好。 小明回想自己的经历:如果一开始就配好了 .gitignore,密钥就不会泄露;如果一开始就选了 Better Auth,就不会想着自己写认证。很多安全问题的根源是"一开始没做对",等到出了事再补救,代价比一开始就做对大得多。这个阶段要确认三件事:.gitignore 配置好了吗?确保 .envnode_modules/.next/ 都在屏蔽列表里——这是你创建项目后应该做的第一件事,甚至在写第一行业务代码之前。.env.example 创建了吗?列出所有需要的环境变量名,不填值,提交到 Git——这是给未来的自己和可能的协作者留的路标。认证方案选好了吗?用 Better Auth 等成熟库,不要自己写——8.2 已经解释了为什么。

跟 AI 说:"帮我检查项目的 .gitignore 是否完整,是否有敏感文件被 Git 追踪。"

开发中——随手检查。 开发过程中最容易犯的错误是"先跑通再说"——密钥先写死在代码里,路由保护先不加,输入校验先跳过。"等功能做完了再回来补",但你永远不会回来补。小明就是这样一步步积累了安全债务,最后一起爆发——密钥泄露、管理后台裸奔、用户输入没校验,每一个都是"先跑通再说"留下的坑。这个阶段要养成随手检查的习惯:密钥都在 .env 里吗?在代码中搜索 sk-passwordsecret 这些关键词,看有没有硬编码的密钥。Server/Client 边界清晰吗?敏感数据只在服务端处理,前端变量加 NEXT_PUBLIC_ 前缀。路由保护到位了吗?Middleware 加 API 内部双重检查。用户输入有校验吗?后端用 Zod 校验所有输入,不信任前端传来的任何数据——前端校验是为了用户体验,后端校验才是为了安全。改了 .env 重启了吗?环境变量只在启动时加载,改了要重启。

跟 AI 说:"审查我的代码,找出所有硬编码的密钥、缺少输入校验的接口、以及没有权限检查的路由。"

上线前——最后一道关。 小明的应用要部署了。他以为把代码推上去就行,但老师傅说:"上线前还有几件事必须检查,不然上线就是裸奔。"依赖有漏洞吗?运行 pnpm audit,修复高危漏洞——你的项目可能间接依赖了几百个包,每个包都可能有已知漏洞。生产环境变量配好了吗?在部署平台的环境变量页面逐一配置,注意有些值在本地和生产环境是不同的(比如 BETTER_AUTH_URL 本地是 http://localhost:3000,生产环境要改成你的域名)。HTTPS 启用了吗?Vercel、Railway 等平台默认启用,自建服务器需要配置——没有 HTTPS,用户的密码和 Cookie 在网络传输中就是明文的,任何人都能截获。错误信息安全吗?生产环境不要返回堆栈信息(stack trace),只返回友好的错误提示——堆栈信息会暴露你的代码结构、文件路径、甚至数据库表名,这些都是攻击者梦寐以求的情报。

上线后——持续维护。 应用上线不是终点,而是另一个起点。小明的应用跑了三个月,某天收到 GitHub 的安全告警邮件:"你的项目依赖 lodash@4.17.20 存在原型污染漏洞。"他很困惑——这个包他从来没直接安装过。查了一下才发现,是他安装的某个包依赖了另一个包,那个包又依赖了这个有漏洞的包。npm 生态就是这样——你的项目可能间接依赖了几百个包,每个包都可能出问题。这个阶段要做的事:密钥每 3-6 个月轮换一次(即使没有泄露,定期更换也是好习惯),每月运行 pnpm audit 检查依赖漏洞,关注异常登录(同一账号短时间内从不同地区登录)、频繁失败的请求(可能是暴力破解)、突增的 API 调用(可能是有人在刷你的接口)。


问题排查手册

安全相关的报错往往让人一头雾水——错误信息不直观,原因可能在你意想不到的地方。小明踩过的每一个坑,都变成了这本手册里的一条。遇到问题?按症状查。

.env 配置了但读不到。 症状是 process.env.XXX 返回 undefined。先重启——环境变量只在启动时加载,Ctrl+C 停掉服务重新 pnpm dev,90% 的问题到这里就解决了。还不行的话,检查变量名拼写是否完全一致(注意大小写),确认 .env 文件在项目根目录(不是在 src/ 里),检查有没有多余的空格或引号——.env 里不需要引号,DATABASE_URL=postgresql://... 是对的,DATABASE_URL="postgresql://..." 可能出问题。

Server 能读到但 Client 读不到。 症状是 API Route 里能读到环境变量,React 组件里是 undefined。原因是没加 NEXT_PUBLIC_ 前缀——这是 Next.js 的安全机制,默认不把环境变量发送到浏览器。如果这个值确实需要在前端使用且不敏感,改名为 NEXT_PUBLIC_XXX。如果是敏感值(API Key),不应该在前端使用——改为在 API Route 里调用。

跨域报错(CORS)。 症状是浏览器控制台显示 Access to fetch at 'xxx' has been blocked by CORS policy。如果前后端在同一个 Next.js 项目里,不应该出现 CORS 问题——检查请求 URL 是否写错了(比如写了完整的 http://localhost:3000/api/... 而不是相对路径 /api/...)。如果调用的是外部 API,需要在后端配置 CORS,允许你的域名访问。有时候是开发环境特有的问题,检查 next.config.js 里的 rewrites 配置。

.gitignore 配了但文件仍被追踪。 症状是 .env 已加入 .gitignore,但 git status 仍然显示它。原因是文件在加入 .gitignore 之前已经被 Git 追踪过——.gitignore 只对"从未被追踪的文件"生效。解决方法是执行 git rm --cached .env 移除缓存,再提交一次。

密钥已经泄露了。 症状是密钥被提交到了 GitHub(公开或私有仓库)。紧急处理四步走:立即去对应平台(OpenAI、Supabase、GitHub 等)重新生成密钥;用新密钥更新 .env;告诉 AI "我的 .env 文件被提交到了 Git 历史中,帮我用 git filter-branch 或 BFG 工具彻底清除";检查账单是否有异常消费。

删除文件再提交不够

git rm .env 然后提交,只是在最新版本里删除了文件。Git 历史中的每一个旧版本仍然包含这个文件。任何人 git log 都能找到。必须清洗历史。

登录后仍被重定向到登录页。 症状是登录成功了,但访问受保护页面还是跳转到 /login。先检查 Cookie 是否正常设置——打开浏览器 F12 → Application → Cookies,看有没有 session cookie。然后确认域名一致——开发环境用 http://localhost:3000,不要用 http://127.0.0.1:3000,Cookie 绑定域名,域名不同 Cookie 不共享。最后检查 Middleware 的 matcher 配置,确认没有把 /login 也保护了(登录页不应该被保护)。

你不需要记住所有这些检查项。定期让 AI 帮你审查:

"审查我的项目安全状况:检查是否有硬编码密钥、.env 是否被 Git 追踪、依赖是否有已知漏洞、所有受保护路由是否都有权限检查。"


本节核心要点

  • 安全清单按阶段执行:开发前配好 .gitignore,开发中检查边界和校验,上线前审计依赖,上线后定期轮换
  • 90% 的 .env 问题重启就能解决
  • .gitignore 只对未追踪的文件生效,已追踪的要先 git rm --cached
  • 密钥泄露后必须重置密钥 + 清洗 Git 历史,光删文件不够

下一步

清单和排查手册都有了,接下来去 进阶安全防护——了解 SQL 注入、XSS、CSRF 等更深层的安全威胁,以及 AI 应用特有的安全问题。