阶段6: 安全加固
目标: 通过 OWASP Top 10 安全审查,让酒店预订系统具备生产级安全防护。
| 模块 | 内容 |
|---|---|
| Module 14 | SQL 注入、XSS、CSRF、密码哈希、密钥管理、限流 |
| Module 12 | JWT 安全(签名算法、过期、刷新) |
| Module 13 | HTTPS、CORS 配置 |
步骤 1:输入校验
Section titled “步骤 1:输入校验”使用 validator 库对所有用户输入做白名单校验。
我的酒店预订系统使用 Go + Gin + GORM。请帮我:
1. 引入 go-playground/validator/v102. 为以下结构体添加校验标签: - CreateBookingRequest: - Email:必填,合法邮箱格式 - CheckIn / CheckOut:必填,日期格式 YYYY-MM-DD,CheckOut > CheckIn - GuestCount:必填,范围 1-10 - RoomType:必填,枚举值 standard/deluxe/suite - RegisterRequest: - Username:必填,3-30 字符,仅字母数字下划线 - Password:必填,8-72 字符 - Email:必填,合法邮箱3. 写一个 Gin 中间件,统一返回校验错误的中文友好提示4. 给出测试用例覆盖边界值步骤 2:SQL 注入防护
Section titled “步骤 2:SQL 注入防护”确认所有数据库操作使用参数化查询。
请审查我的酒店预订系统代码,检查 SQL 注入风险:
1. 列出所有使用 db.Raw() / db.Exec() 的地方,确认是否用了 ? 占位符2. 检查是否有字符串拼接 SQL 的情况3. 确认 GORM 的 Where/Find/Create 是否都使用了结构体或 map 传参4. 如果发现不安全的写法,给出修复代码5. 特别检查搜索功能——按城市/日期/价格区间搜索房间的查询
给出一份审查报告,格式:文件名 → 行号 → 风险等级 → 修复建议步骤 3:XSS 防护
Section titled “步骤 3:XSS 防护”确保所有输出经过转义。
请帮我检查并加固酒店预订系统的 XSS 防护:
1. 后端: - 对所有用户输入的文本字段(酒店名称、评论、地址)在存储前做 HTML 转义 - 使用 bluemonday 库对富文本字段做白名单过滤 - 给出中间件代码
2. 前端(React): - 确认没有使用 dangerouslySetInnerHTML - 如果必须渲染富文本,使用 DOMPurify 清洗 - 检查 URL 参数是否直接渲染到页面
3. API 响应头添加:Content-Type: application/json; charset=utf-8
给出具体的代码修改。步骤 4:CSRF 防护
Section titled “步骤 4:CSRF 防护”确保 API 不受跨站请求伪造攻击。
请帮我为酒店预订系统配置 CSRF 防护:
1. 确认认证方式: - 如果用 Cookie 存 JWT:设置 SameSite=Strict, HttpOnly, Secure - 如果用 Authorization Header:说明为什么天然防 CSRF2. 如果当前用 localStorage 存 token: - 评估风险(XSS 可窃取) - 建议改为 HttpOnly Cookie + SameSite=Strict - 给出 Gin 设置 Cookie 的代码3. 对于表单提交(如果有):添加 CSRF Token 机制4. 确认 CORS 配置只允许前端域名
给出完整的认证中间件代码。步骤 5:安全 Headers
Section titled “步骤 5:安全 Headers”添加安全响应头。
请帮我为酒店预订系统(Go + Gin)添加安全响应头中间件:
1. X-Content-Type-Options: nosniff2. X-Frame-Options: DENY3. X-XSS-Protection: 0(现代浏览器不需要,避免副作用)4. Referrer-Policy: strict-origin-when-cross-origin5. Content-Security-Policy: - default-src 'self' - script-src 'self'(如果用 Vite 开发需要调整) - style-src 'self' 'unsafe-inline'(Tailwind 需要) - img-src 'self' data: https: - connect-src 'self'6. Strict-Transport-Security: max-age=31536000; includeSubDomains(生产环境)
写成 Gin 中间件,区分开发/生产环境的 CSP 配置。步骤 6:限流
Section titled “步骤 6:限流”使用 Redis 滑动窗口实现 API 限流。
请帮我为酒店预订系统实现 API 限流:
1. 使用 Redis 滑动窗口算法2. 限流规则: - 公开 API(搜索房间):60 次/分钟/IP - 登录 API:10 次/分钟/IP - 预订 API:20 次/分钟/用户 - 全局兜底:1000 次/分钟/IP3. 实现 Gin 中间件: - 从 X-Real-IP 或 X-Forwarded-For 获取真实 IP - 返回 429 状态码 + Retry-After 头 - 添加 X-RateLimit-Remaining / X-RateLimit-Reset 响应头4. Redis 连接复用现有连接池5. Redis 不可用时 fallback 到内存限流(golang.org/x/time/rate)
给出完整代码,包括 Redis Lua 脚本和中间件。步骤 7:敏感信息管理
Section titled “步骤 7:敏感信息管理”确保无密钥泄露、无敏感数据暴露。
请帮我审查酒店预订系统的敏感信息管理:
1. 环境变量检查: - 确认 .env 在 .gitignore 中 - 确认无硬编码的密钥、数据库密码、API Key - 给出 .env.example 模板(只有键名无值)
2. API 返回脱敏: - 用户接口不返回 password_hash - 预订接口脱敏手机号(138****1234)和邮箱(a**@example.com) - 管理后台接口可以返回完整信息
3. 错误信息脱敏: - 生产环境不返回堆栈信息 - 数据库错误统一返回"服务器内部错误" - 开发环境可以返回详细错误
4. 日志脱敏: - 日志中不打印密码、token 完整值 - 信用卡号只记录后四位
给出具体的代码修改。步骤 8:依赖安全
Section titled “步骤 8:依赖安全”检查第三方依赖的已知漏洞。
请帮我建立酒店预订系统的依赖安全检查流程:
1. Go 后端: - 运行 govulncheck ./... 检查已知漏洞 - 运行 go list -m -json all | nancy sleuth(或 trivy) - 更新有漏洞的依赖
2. React 前端: - 运行 npm audit - 修复 high/critical 级别漏洞 - 运行 npm outdated 检查过期依赖
3. Docker 镜像: - 使用 trivy 扫描构建后的镜像 - 基础镜像使用 alpine 减少攻击面
4. 给出一个可以定期运行的安全检查脚本(check-security.sh)
列出当前发现的所有问题及修复方案。- 所有用户输入都有 validator 校验标签
- 无字符串拼接 SQL,全部使用参数化查询
- 前端无 dangerouslySetInnerHTML,后端有 HTML 转义
- Cookie 设置了 SameSite + HttpOnly + Secure
- 安全 Headers 中间件已添加(CSP/HSTS/X-Frame-Options)
- 限流中间件已生效(登录 10/min,搜索 60/min)
- .env 在 .gitignore,无硬编码密钥,API 返回已脱敏
- npm audit 和 govulncheck 无 high/critical 漏洞
- 错误响应不泄露内部实现细节
-
CSP 太严导致前端白屏: Vite 开发模式使用 inline script/style,开发环境的 CSP 需要放宽(加
'unsafe-inline'或 nonce),生产环境再收紧。上线前务必在生产构建下测试。 -
限流的 Key 搞错了: 在反向代理后面,
c.ClientIP()拿到的可能是 127.0.0.1。必须配置 Gin 信任的代理(gin.SetTrustedProxies)并使用X-Real-IP头。不配置信任代理等于没有限流。 -
JWT 放 localStorage 还是 Cookie: localStorage 方便但 XSS 可偷;HttpOnly Cookie 安全但需要处理 CSRF 和跨域。推荐 SPA 用 HttpOnly Cookie + SameSite=Strict。如果已经用了 localStorage,先确保 XSS 防护到位。
-
CORS 配置
*通配符: 开发时图方便设了AllowAllOrigins: true,上线忘记改回来。生产环境必须指定确切的前端域名,且不能同时设置AllowCredentials: true和AllowAllOrigins: true(浏览器会拒绝)。 -
密码哈希用了 MD5/SHA256: 这些是摘要算法不是密码哈希算法。必须用 bcrypt(推荐 cost=12)或 argon2id。GORM Hook 的
BeforeCreate里做哈希,别在 handler 里手动处理,避免漏掉。