从裸奔到加固:我的校园论坛网络安全实战

本文记录了一个大二学生在开发校园论坛时,为即将开始的班级试点进行网络安全加固的全过程。如果你也在独立做全栈项目,希望这些经验能帮你少踩几个坑。

前言

我的校园论坛(江农论坛)已经完成了核心功能开发------帖子发布、评论互动、分区浏览、树洞匿名、首页推荐、个人主页、管理员审核、白名单注册。在准备向全班同学推广之前,我意识到一个严重的问题:项目一直在"裸奔"

后端 cors() 允许所有来源访问,没有频率限制,请求体大小不受控,HTTP 安全头一个都没配。这就像一个房子装修好了,但门窗全开着。

今天的目标很明确:在试点之前,把安全加固做完。

一、CORS 白名单:别让所有人都能调你的 API

问题

项目初期为了开发方便,后端直接用了 app.use(cors()),这行代码的意思是"允许任何网站跨域请求我的 API"。在生产环境里,这意味着任何网站都可以用 JavaScript 调用你的接口,用你用户的身份发帖、评论。

解决方案

改成只允许自己的域名和本地开发地址:

javascript 复制代码
app.use(cors({
  origin: [
    'https://www.aoliforum.me',
    'https://aoliforum.me',
    'http://localhost:5173'
  ],
  credentials: true
}))

踩坑点

如果你的前端和后端不在同一个域名下(我的前端在 Vercel,后端在 Railway),并且前端请求时带了 Authorization 头,那么 credentials: true 是必须的。否则浏览器不会发送 Cookie 和 Authorization 头。


二、请求体大小限制:防止恶意超大请求

问题

Express 默认不限制请求体大小。如果有人恶意发送一个巨大的 JSON 请求,你的服务器可能会内存溢出或响应变慢。

解决方案

javascript 复制代码
app.use(express.json({ limit: '1mb' }))

这行代码限制所有请求体不超过 1MB。对于论坛场景(纯文本帖子、评论),1MB 已经非常充裕。如果以后接入了图片上传,图片走七牛云直传,不会经过这个限制。


三、接口防刷:别让人暴力破解和批量注册

问题

登录接口如果没有任何限制,攻击者可以用脚本暴力破解密码。注册接口没限制,可以批量注册垃圾账号。

解决方案

express-rate-limit 对不同接口设置不同的频率限制:

javascript 复制代码
const rateLimit = require('express-rate-limit')

// 登录接口:15分钟最多10次
const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 10,
  message: { error: '登录尝试过多,请15分钟后再试' }
})
app.use('/api/users/login', loginLimiter)

// 注册接口:1小时最多3次
const registerLimiter = rateLimit({
  windowMs: 60 * 60 * 1000,
  max: 3,
  message: { error: '注册请求过于频繁,请稍后再试' }
})
app.use('/api/users/register', registerLimiter)

踩坑点

app.use顺序非常重要 。限速中间件必须放在路由注册之前,否则不会生效。我一开始把 rateLimit 的代码放在了路由注册之后,测试时发现完全没限制,排查了半天才发现是顺序问题。


四、Helmet 安全头:给你的 HTTP 响应穿上盔甲

问题

Express 默认不会添加任何安全相关的 HTTP 头。这意味着你的网站容易被点击劫持、MIME 类型嗅探、XSS 等攻击。

解决方案

安装 helmet 并配置:

javascript 复制代码
const helmet = require('helmet')

app.use(helmet({
  crossOriginResourcePolicy: { policy: 'cross-origin' },
  contentSecurityPolicy: false
}))

踩坑点

helmet 默认会启用 CSP(内容安全策略),它会限制页面可以加载哪些来源的资源。但我的前端和后端不同域,前端需要跨域请求后端 API,默认的 CSP 策略会拦截这些请求,导致论坛完全不可用。

解决方案是关闭 CSP(contentSecurityPolicy: false),同时把 crossOriginResourcePolicy 设为 cross-origin,允许跨域资源加载。这不是最佳实践,但对于前后端分离的小项目来说,这是最务实的做法。


五、环境变量与依赖安全

环境变量

检查 .gitignore 是否包含了 .env 文件:

bash 复制代码
backend/.env
.env

然后用 git log 确认历史记录里没有误提交过 .env 文件。如果提交过,需要立即更换数据库密码和 JWT 密钥。

依赖安全

运行 npm audit 检查依赖漏洞。我的项目发现 mongo-express 有 3 个低危漏洞。mongo-express 是 MongoDB 的 Web 管理界面,只是一个开发工具,不暴露在公网,但为了零漏洞,我直接卸载了它,用 MongoDB Compass 和 Atlas 网页界面替代。


总结与感受

这次安全加固让我意识到:功能开发和安全加固是两件完全不同的事。 功能开发是"让东西跑起来",安全加固是"让东西不被搞垮"。前者追求速度,后者追求防御深度。

分享几点体会:

  1. CORS 白名单是底线 :永远不要在生产环境用 cors() 通配符。这是最低成本的防护,也是最容易被忽视的。
  2. 限速配置要区分场景:登录、注册、发帖、评论,不同接口的风险不同,限速策略也应该不同。一刀切的全局限制要么太松(登录被刷),要么太紧(正常用户被误伤)。
  3. Helmet 不是"装上就行":它默认的 CSP 策略会让前后端分离的项目挂掉。你需要理解每个安全头的作用,而不是盲目装包。
  4. 环境变量泄露是不可逆的 :一旦 .env 被提交到 Git,你的密码就永远留在历史记录里了。唯一的补救是立即更换密钥。
  5. 依赖安全要定期检查npm audit 只需要几秒钟,但它能在漏洞被利用之前提醒你。

项目状态更新:

  • 在线地址:aoliforum.me
  • 已完成功能:帖子发布、评论互动、游客模式、分区浏览、树洞匿名、首页推荐、个人主页、管理员审核、白名单注册、联系通道
  • 已完成安全加固:CORS 白名单、接口防刷、Helmet 安全头、请求体限制、环境变量与依赖安全
  • 待完成:消息通知

如果你也在独立做全栈项目,欢迎评论区交流你的安全实践。

相关推荐
没事别瞎琢磨1 小时前
十一、审计与 Run Session——每一步操作都被记录
人工智能·node.js
没事别瞎琢磨1 小时前
十六、AgentSandbox——把所有模块串起来的编排类
人工智能·node.js
没事别瞎琢磨1 小时前
十二、网络代理与白名单规则引擎
人工智能·node.js
没事别瞎琢磨1 小时前
十四、Git Worktree 隔离执行
人工智能·node.js
没事别瞎琢磨2 小时前
十、统一 Runner 入口——能力检测与模式回退
人工智能·node.js
没事别瞎琢磨3 小时前
八、环境隔离——构建安全的子进程环境
人工智能·node.js
没事别瞎琢磨4 小时前
六、输出捕获与截断
人工智能·node.js
没事别瞎琢磨4 小时前
七、敏感路径预检——Protected Paths
人工智能·node.js
没事别瞎琢磨4 小时前
五、进程执行——spawn、超时与进程树清理
人工智能·node.js
没事别瞎琢磨4 小时前
四、命令风险分级与审批策略
人工智能·node.js