练习题与综合作业
以下练习先不给答案。建议每题都用浏览器 Network/Console 和 curl 双重验证,并记录“请求是否到达后端”与“浏览器是否允许读取响应”这两个不同结论。
一、基础练习
1. 判断 Origin
页面地址为 https://www.example.com:443/app,判断下面请求是否同源,并说明依据:
https://www.example.com/api/usershttp://www.example.com/api/usershttps://api.example.com/api/usershttps://www.example.com:8443/api/users
2. Vite + Express
前端运行于 http://localhost:5173,API 运行于 http://localhost:8080。实现仅允许该前端访问的 CORS 配置,并完成 GET 与 JSON POST 测试。
要求:
- 使用 TypeScript 显式声明
CorsOptions。 - 用 curl 模拟 POST 的 OPTIONS 预检。
- 解释为什么普通 curl 成功不能证明浏览器一定成功。
3. Bearer Token
实现 /api/profile:要求携带 Authorization Bearer Token。让浏览器跨源请求成功,并列出预检响应必须包含的 Header。
4. Header 检查
启用 helmet() 后,使用 curl -i 记录实际 Header。逐项标注哪些来自 Express、Helmet、cors 和 Node.js,并说明你判断的依据。
二、排错练习
5. OPTIONS 401
一个项目的 JWT 中间件位于 CORS 中间件之前,浏览器 POST 总是在 OPTIONS 阶段收到 401。请设计修复方案,并说明为什么预检不应依赖正式请求的 Bearer Token。
6. Postman 正常、浏览器失败
接口在 Postman 返回 200,但浏览器 Console 报 CORS。请给出至少六个检查步骤,涵盖 Origin、OPTIONS、正式响应、重定向、Nginx 和 CSP。
7. 错误响应不可见
成功响应正常,只有 500 响应被浏览器显示为 CORS 错误。找出可能的中间件顺序问题,并设计 curl 验证命令。
8. 重复 Allow-Origin
Nginx 和 Express 都添加了 Access-Control-Allow-Origin。curl 看到两个不同值。说明浏览器为什么不会把它们当作两个合法来源,并选择一层负责管理。
9. CSP 拦截连接
API 的 CORS 配置完全正确,但页面 Console 报 connect-src 违规。说明应该修改哪个响应上的哪个策略,并解释为什么修改 API 的 CORS 没用。
三、文件与页面练习
10. 跨域下载
实现一个跨域 CSV 下载接口:
- 下载时保留中文文件名。
- 前端能读取
Content-Disposition。 - 使用 curl 验证响应头。
- 不允许用户通过 URL 参数读取任意服务器文件。
11. 图片服务
图片从 https://files.example.com 提供,页面位于 https://www.example.com。浏览器报告资源策略错误。分别从页面 CSP、图片 CORP 和 CORS 三个角度设计排查实验。
12. Markdown HTML 预览
为上传 Markdown ZIP 后生成的 HTML 设计预览策略。要求:
- 禁止用户脚本执行。
- 允许服务端高亮后的 CSS。
- 允许本域图片和 data URL 图片。
- 禁止表单提交和网络请求。
- 讨论独立预览域名和 iframe sandbox 的价值。
四、部署练习
13. 同域部署
设计 Nginx 配置:/ 返回前端静态文件,/api/ 代理到 127.0.0.1:8080。判断是否需要 CORS,并说明页面 CSP、HSTS 和 API Helmet 分别放在哪里。
14. 跨子域 Bearer
页面位于 www.example.com,API 位于 api.example.com。实现生产白名单,允许 Authorization,暴露 X-Request-Id,并设置合理的预检缓存。
15. 跨源 Cookie
把上一题改为 Cookie Session 登录。列出前端、CORS、Cookie、HTTPS 和 CSRF 五个方面都要完成的配置,并解释为什么 Origin 不能用 *。
16. 环境变量校验
从 CORS_ALLOWED_ORIGINS 读取逗号分隔的生产白名单。要求:
- 启动时校验每项是合法的
http:或https:URL。 - 去重并移除末尾斜杠带来的配置歧义。
- 生产配置为空时拒绝启动,不能退化成
*。 - 没有 Origin 的服务间调用可以正常工作,但仍需认证。
五、综合作业
17. 安全上线一个文档转换服务
为以下接口设计并实现 Helmet、CORS 和 Nginx 策略:
POST /api/exports 上传 Markdown ZIP
GET /api/exports/:id 查询处理状态
GET /api/exports/:id/download 下载生成 ZIP
GET /preview/:id/index.html 在线预览生成 HTML
交付物应包括:
- Express 5 + TypeScript 中间件配置。
- Nginx 静态页面与
/api代理配置。 - Bearer Token 方案;可选扩展 Cookie 方案。
- CSP Report-Only 到强制执行的发布计划。
- 正常、OPTIONS、401、404、500、下载和预览的 curl 验证命令。
- 浏览器回归检查表。
- Header 配置出错时的回滚方案。
完成后请复盘:哪些策略是浏览器执行的,哪些是服务端真正的认证或输入安全措施;Helmet 和 CORS 各自无法解决哪些风险。