whistle 如何解决跨域问题,有哪些常见的跨域场景?
答案Whistle 提供了多种方式来处理跨域问题,可以在开发环境中快速解决 CORS 相关问题。跨域问题基础1. 什么是跨域跨域是指浏览器出于安全考虑,限制从一个域名的网页向另一个域名的资源发起请求。同源策略限制:协议不同(http vs https)域名不同(example.com vs test.com)端口不同(80 vs 8080)2. CORS 响应头解决跨域需要服务器返回正确的 CORS 响应头:Access-Control-Allow-Origin:允许的源Access-Control-Allow-Methods:允许的 HTTP 方法Access-Control-Allow-Headers:允许的请求头Access-Control-Allow-Credentials:是否允许携带凭证Access-Control-Max-Age:预检请求的缓存时间使用 whistle 解决跨域1. 添加 CORS 响应头创建 CORS 响应头文件:cors-headers.json{ "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS, PATCH", "Access-Control-Allow-Headers": "Content-Type, Authorization, X-Requested-With", "Access-Control-Allow-Credentials": "true", "Access-Control-Max-Age": "86400"}配置规则:www.example.com resHeaders://{cors-headers.json}api.example.com resHeaders://{cors-headers.json}2. 针对特定域名创建特定域名的 CORS 响应头:cors-specific.json{ "Access-Control-Allow-Origin": "https://www.myapp.com", "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", "Access-Control-Allow-Headers": "Content-Type, Authorization", "Access-Control-Allow-Credentials": "true"}配置规则:api.example.com resHeaders://{cors-specific.json}3. 处理预检请求创建脚本:handle-preflight.jsmodule.exports = function(req, res) { // 处理 OPTIONS 预检请求 if (req.method === 'OPTIONS') { res.statusCode = 204; res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); res.setHeader('Access-Control-Max-Age', '86400'); res.end(); }};配置规则:api.example.com reqScript://{handle-preflight.js}高级跨域处理1. 动态设置 Allow-Origin创建脚本:dynamic-cors.jsmodule.exports = function(req, res) { const originalEnd = res.end; res.end = function(chunk, encoding) { // 动态设置允许的源 const origin = req.headers['origin']; if (origin) { res.setHeader('Access-Control-Allow-Origin', origin); res.setHeader('Access-Control-Allow-Credentials', 'true'); } originalEnd.call(res, chunk, encoding); };};配置规则:api.example.com resScript://{dynamic-cors.js}2. 根据请求路径设置不同的 CORS 策略创建脚本:path-based-cors.jsmodule.exports = function(req, res) { const originalEnd = res.end; res.end = function(chunk, encoding) { // 根据路径设置不同的 CORS 策略 if (req.url.startsWith('/api/public/')) { res.setHeader('Access-Control-Allow-Origin', '*'); } else if (req.url.startsWith('/api/private/')) { const origin = req.headers['origin']; if (origin && origin.includes('myapp.com')) { res.setHeader('Access-Control-Allow-Origin', origin); res.setHeader('Access-Control-Allow-Credentials', 'true'); } } originalEnd.call(res, chunk, encoding); };};配置规则:api.example.com resScript://{path-based-cors.js}3. 代理到同源使用 forward 操作符:api.example.com forward http://127.0.0.1:3000或者使用 host 操作符:api.example.com host 127.0.0.1:3000常见跨域场景1. 前端开发本地调试场景:前端在 localhost:3000,后端在 api.example.com解决方案:# 添加 CORS 响应头api.example.com resHeaders://{cors-headers.json}# 或者将后端代理到本地api.example.com host 127.0.0.1:80802. 多个子域名之间通信场景:www.example.com 需要访问 api.example.com解决方案:# 允许特定子域名api.example.com resHeaders://{cors-subdomain.json}cors-subdomain.json:{ "Access-Control-Allow-Origin": "https://www.example.com", "Access-Control-Allow-Credentials": "true"}3. 携带凭证的请求场景:需要携带 Cookie 或 Authorization 头的请求解决方案:api.example.com resHeaders://{cors-with-credentials.json}cors-with-credentials.json:{ "Access-Control-Allow-Origin": "https://www.myapp.com", "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Authorization"}跨域调试技巧1. 查看预检请求在 whistle 管理界面中:点击 "Network" 标签筛选 "OPTIONS" 方法的请求查看请求和响应头检查 CORS 响应头是否正确2. 验证 CORS 配置创建验证脚本:verify-cors.jsmodule.exports = function(req, res) { console.log('Request Origin:', req.headers['origin']); console.log('Request Method:', req.method); console.log('Request Headers:', req.headers['access-control-request-headers']); const originalEnd = res.end; res.end = function(chunk, encoding) { console.log('Response CORS Headers:'); console.log(' Access-Control-Allow-Origin:', res.getHeader('Access-Control-Allow-Origin')); console.log(' Access-Control-Allow-Methods:', res.getHeader('Access-Control-Allow-Methods')); console.log(' Access-Control-Allow-Headers:', res.getHeader('Access-Control-Allow-Headers')); originalEnd.call(res, chunk, encoding); };};配置规则:api.example.com resScript://{verify-cors.js}3. 模拟不同的源创建脚本:simulate-origin.jsmodule.exports = function(req, res) { // 模拟不同的请求源 const origins = [ 'https://www.example.com', 'https://test.example.com', 'https://localhost:3000' ]; // 随机选择一个源 const randomOrigin = origins[Math.floor(Math.random() * origins.length)]; req.headers['origin'] = randomOrigin; console.log('Simulated Origin:', randomOrigin);};配置规则:api.example.com reqScript://{simulate-origin.js}最佳实践开发环境使用宽松的 CORS 策略允许所有源:*方便开发和测试生产环境使用严格的 CORS 策略只允许特定的源启用凭证验证定期检查 CORS 配置确保响应头正确避免安全漏洞使用环境变量管理 CORS 配置开发环境:宽松策略生产环境:严格策略文档化 CORS 策略记录允许的源说明特殊处理逻辑