跨域策略如何安全配置

wen 网络安全 32

本文目录导读:

跨域策略如何安全配置

  1. 核心响应头:Access-Control-Allow-Origin
  2. 处理凭据:Access-Control-Allow-Credentials
  3. 限制HTTP方法:Access-Control-Allow-Methods
  4. 限制自定义请求头:Access-Control-Allow-Headers
  5. 缓存预检请求:Access-Control-Max-Age
  6. 服务器端处理逻辑(举例:Node.js中间件)
  7. 进阶安全策略
  8. 安全CORS清单

跨域策略(CORS)安全配置的核心原则是最小权限原则:只允许你信任的源、只允许必须的HTTP方法、只暴露必要的数据、避免使用通配符,以下是从基础到进阶的安全配置指南。

核心响应头:Access-Control-Allow-Origin

这是最关键的头,它决定哪个外部源可以访问你的资源。

  • ✅ 安全做法:明确指定具体域名

    • 只对已知且必要的源授权。
    • 正确示例:Access-Control-Allow-Origin: https://your-frontend.example.com
    • 错误示例:Access-Control-Allow-Origin: *(通配符)
  • *❌ 避免使用通配符 `` 的场景**

    • 当请求中包含凭据(cookies、HTTP认证、客户端SSL证书)时,不允许使用 。
    • 当资源是非公开(仅限登录用户使用)时。
    • 当你需要根据请求动态返回源时(配合Origin头做验证)。
  • ✅ 安全做法:动态验证请求头

    • 服务器端应检查请求中的 Origin 头,如果它在你的白名单中,则返回该具体源;否则返回错误或不设置CORS头。
    • 关键逻辑不要简单地原样返回 Origin 头,必须做白名单验证。

处理凭据:Access-Control-Allow-Credentials

如果需要携带cookie或Authorization头进行跨域请求,此头必须设置为 true

  • ✅ 安全做法

    • Access-Control-Allow-Credentials: true
    • 同时必须Access-Control-Allow-Origin 不能为 ,必须是具体的源
    • 同时必须Access-Control-Expose-Headers 不能包含 ,必须是具体的头
    • 注意:如果后端有这个头,前端AJAX请求必须设置 withCredentials: true,否则浏览器会拒绝响应。
  • ❌ 不安全做法

    允许携带凭据的同时,源设置成 ,这是最常见的配置错误,浏览器会直接报错并阻止请求。

限制HTTP方法:Access-Control-Allow-Methods

仅允许你预期使用的HTTP方法。

  • ✅ 安全做法
    • Access-Control-Allow-Methods: GET, POST, PUT
    • 避免 Access-Control-Allow-Methods: OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT, PATCH
    • 特别要禁用 PUTDELETEPATCH 如果业务不需要,如果业务需要,则保留。
    • 更安全的做法:如果API只读,就只允许 GET

限制自定义请求头:Access-Control-Allow-Headers

仅允许必要的、非简单的请求头。

  • ✅ 安全做法
    • Access-Control-Allow-Headers: X-Custom-Header, Content-Type
    • 避免 Access-Control-Allow-Headers: *

缓存预检请求:Access-Control-Max-Age

预检请求(OPTIONS)会增加一次往返,可以缓存它。

  • ✅ 安全做法
    • 设置一个合理的长时间(如 86400 秒,即24小时)。
    • Access-Control-Max-Age: 86400

服务器端处理逻辑(举例:Node.js中间件)

这是一个安全的CORS中间件示例逻辑,不依赖第三方库:

const ALLOWED_ORIGINS = [
  'https://your-frontend.example.com',
  'https://admin.your-app.com'
];
function corsMiddleware(req, res, next) {
  const origin = req.headers.origin;
  // 1. 检查Origin是否在白名单中
  if (ALLOWED_ORIGINS.includes(origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin);
    // 2. 凭据配置
    res.setHeader('Access-Control-Allow-Credentials', 'true');
    // 3. 处理预检请求
    if (req.method === 'OPTIONS') {
      res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT');
      // 只允许必要的请求头
      res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
      res.setHeader('Access-Control-Max-Age', '86400'); // 24 hours
      return res.status(204).end();
    }
  } else {
    // 对于不在白名单的请求,通常不设置CORS头(浏览器会拒绝)
    // 或者返回403,但更安全是不设置任何头
  }
  next();
}
// 使用
app.use(corsMiddleware);

进阶安全策略

  • 不要信任 Origin 头的格式:验证 Origin 的完全匹配,包括协议(https://)、域名、端口。http://evil.example.comhttps://example.com 不同。
  • *禁止 `Credentials` 的混合**:这是最常见的安全漏洞。
  • 限制暴露响应头Access-Control-Expose-Headers 只暴露前端真正需要的响应头。
  • 避免使用 Vary: Origin:如果动态返回源,建议主动设置 Vary: Origin,但某些CDN或代理会缓存第一个请求的源,导致后续其他源被错误返回,更安全的做法是在CDN层不做CORS相关的缓存
  • 如果你的服务是静态资源(图片、CSS):如果资源完全是公开的(无需登录、无敏感数据),可以用 Access-Control-Allow-Origin: *,但即使如此,也要谨慎,因为其他网站可以嵌入。

安全CORS清单

配置项 推荐安全值 不安全/危险做法
Access-Control-Allow-Origin 具体的、白名单验证后的源 或直接返回未验证的 Origin
Access-Control-Allow-Credentials true(仅在需要凭据时) 与 一起使用 / 不必要地开启
Access-Control-Allow-Methods 业务需要的具体方法 或包含不必要的方法
Access-Control-Allow-Headers 业务需要的具体头 或包含敏感头
Origin白名单验证 必须在服务器端做 完全不验证或任意匹配
预检请求处理 限制方法、头、Max-Age 允许所有

安全配置不是一个静态的开关,而是一个动态的、基于业务需求的最小权限集合,定期审查你的 Access-Control-* 配置,确保没有过度授权。

抱歉,评论功能暂时关闭!