云计算百科
云计算领域专业知识百科平台

服务端配置 CORS解决跨域问题的原理

服务端配置 CORS(跨域资源共享)的原理本质是 浏览器与服务器之间的安全协商机制。其核心在于服务器通过特定的 HTTP 响应头声明允许哪些外部源(Origin)访问资源,浏览器根据这些响应头决定是否放行跨域请求。以下是详细原理分解:


一、核心流程:浏览器与服务端的协作机制

场景:网页 https://web.com 请求 https://api.com/data
  • 浏览器发起跨域请求

    • 自动在请求头中添加 Origin: https://web.com(表明请求来源)。
  • 服务端响应

    • 检查 Origin 值是否在允许列表中。
    • 若允许,则在响应头中添加 CORS 相关字段(如 Access-Control-Allow-Origin: https://web.com)。
    • 若拒绝,不添加 CORS 头或返回错误(浏览器会拦截响应)。
  • 浏览器验证响应头

    • 检查响应头是否包含 Access-Control-Allow-Origin 且值与当前 Origin 匹配(或为 *)。
    • 验证通过 → 解除拦截,网页可读取响应数据。
    • 验证失败 → 抛出 CORS 错误(如 No 'Access-Control-Allow-Origin' header)。

  • 二、关键 HTTP 响应头字段解析

    服务器通过以下头字段声明跨域规则:

    响应头字段作用示例
    Access-Control-Allow-Origin 必选,声明允许访问的源(域名) https://web.com 或 *
    Access-Control-Allow-Methods 声明允许的 HTTP 方法(如 GET、POST) GET, POST, PUT
    Access-Control-Allow-Headers 声明允许客户端携带的请求头(如 Content-Type) Content-Type, Authorization
    Access-Control-Allow-Credentials 是否允许发送 Cookie 等凭证(需客户端设置 withCredentials: true) true
    Access-Control-Max-Age 预检请求(OPTIONS)的缓存时间(秒),减少重复预检 86400(24小时)

    ⚠️ 注意:若请求需携带 Cookie(凭证),则:

    • 服务端必须设置 Access-Control-Allow-Credentials: true
    • 服务端的 Access-Control-Allow-Origin 不能为 *,必须明确指定域名(如 https://web.com)
    • 客户端需设置 withCredentials: true(如 Fetch API 或 Axios)。

    三、预检请求(Preflight Request):复杂请求的二次确认

    当请求满足以下任一条件时,浏览器会先发送 OPTIONS 预检请求(非简单请求):

  • 使用了 PUT、DELETE 等非简单方法(简单方法仅限 GET、POST、HEAD)。
  • 携带了自定义请求头(如 Authorization)。
  • Content-Type 为 application/json 等非简单类型(简单类型仅限 application/x-www-form-urlencoded、multipart/form-data、text/plain)。
  • 预检请求工作流程:

    #mermaid-svg-eoXfYt6ZK3wHQ67B {font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-eoXfYt6ZK3wHQ67B .error-icon{fill:#552222;}#mermaid-svg-eoXfYt6ZK3wHQ67B .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eoXfYt6ZK3wHQ67B .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-eoXfYt6ZK3wHQ67B .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eoXfYt6ZK3wHQ67B .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eoXfYt6ZK3wHQ67B .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eoXfYt6ZK3wHQ67B .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eoXfYt6ZK3wHQ67B .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eoXfYt6ZK3wHQ67B .marker.cross{stroke:#333333;}#mermaid-svg-eoXfYt6ZK3wHQ67B svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eoXfYt6ZK3wHQ67B .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-eoXfYt6ZK3wHQ67B text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-eoXfYt6ZK3wHQ67B .actor-line{stroke:grey;}#mermaid-svg-eoXfYt6ZK3wHQ67B .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-eoXfYt6ZK3wHQ67B .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-eoXfYt6ZK3wHQ67B #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-eoXfYt6ZK3wHQ67B .sequenceNumber{fill:white;}#mermaid-svg-eoXfYt6ZK3wHQ67B #sequencenumber{fill:#333;}#mermaid-svg-eoXfYt6ZK3wHQ67B #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-eoXfYt6ZK3wHQ67B .messageText{fill:#333;stroke:#333;}#mermaid-svg-eoXfYt6ZK3wHQ67B .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-eoXfYt6ZK3wHQ67B .labelText,#mermaid-svg-eoXfYt6ZK3wHQ67B .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-eoXfYt6ZK3wHQ67B .loopText,#mermaid-svg-eoXfYt6ZK3wHQ67B .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-eoXfYt6ZK3wHQ67B .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-eoXfYt6ZK3wHQ67B .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-eoXfYt6ZK3wHQ67B .noteText,#mermaid-svg-eoXfYt6ZK3wHQ67B .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-eoXfYt6ZK3wHQ67B .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-eoXfYt6ZK3wHQ67B .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-eoXfYt6ZK3wHQ67B .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-eoXfYt6ZK3wHQ67B .actorPopupMenu{position:absolute;}#mermaid-svg-eoXfYt6ZK3wHQ67B .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-eoXfYt6ZK3wHQ67B .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-eoXfYt6ZK3wHQ67B .actor-man circle,#mermaid-svg-eoXfYt6ZK3wHQ67B line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-eoXfYt6ZK3wHQ67B :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}BrowserServerOPTIONS 预检请求携带:Origin: https://web.comAccess-Control-Request-Method: PUTAccess-Control-Request-Headers: Content-Type响应预检结果返回:Access-Control-Allow-Origin: https://web.comAccess-Control-Allow-Methods: PUTAccess-Control-Allow-Headers: Content-Type发送真实请求(PUT)返回真实数据BrowserServer


    四、CORS 的安全本质:服务端控制权限

  • 主动权在服务端

    • 浏览器只是执行者,实际放行权由服务端通过响应头控制。
    • 若服务器未返回正确的 CORS 头,即使接口本身能正常响应(如用 Postman 测试成功),浏览器仍会拦截。
  • 防御恶意网站

    • 假设用户访问了恶意网站 evil.com,该网站尝试请求 bank.com 的 API:
      • bank.com 的服务器检测到 Origin: evil.com 不在白名单中 → 不返回 CORS 头。
      • 浏览器拦截响应 → evil.com 无法读取 bank.com 的数据。

  • 五、配置示例:Node.js 中的 CORS 中间件

    const express = require('express');
    const cors = require('cors');

    const app = express();

    // 基础配置:允许所有源访问(慎用!)
    app.use(cors());

    // 精细化配置(推荐)
    app.use(cors({
    origin: 'https://web.com', // 仅允许指定源
    methods: ['GET', 'POST'], // 允许的方法
    allowedHeaders: ['Content-Type'], // 允许的请求头
    credentials: true, // 允许携带凭证
    maxAge: 86400 // 预检缓存时间
    }));

    app.get('/data', (req, res) => {
    res.json({ data: "跨域数据返回成功!" });
    });


    六、常见误区澄清

    误区真相
    “CORS 是服务端的安全漏洞” CORS 是安全机制,没有它浏览器会默认禁止跨域
    “JSONP 能替代 CORS” JSONP 仅支持 GET,且存在安全风险(如 XSS)
    “前端代码可绕过 CORS 限制” 浏览器会强制检查响应头,前端无法绕过
    “服务端不配置 CORS = 接口无法访问” 接口仍可被 curl、Postman 等工具调用,但浏览器会拦截

    总结:CORS 的核心原理

    #mermaid-svg-sl4ODSvoOnTmtYQW {font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-sl4ODSvoOnTmtYQW .error-icon{fill:#552222;}#mermaid-svg-sl4ODSvoOnTmtYQW .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-sl4ODSvoOnTmtYQW .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-sl4ODSvoOnTmtYQW .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-sl4ODSvoOnTmtYQW .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-sl4ODSvoOnTmtYQW .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-sl4ODSvoOnTmtYQW .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-sl4ODSvoOnTmtYQW .marker{fill:#333333;stroke:#333333;}#mermaid-svg-sl4ODSvoOnTmtYQW .marker.cross{stroke:#333333;}#mermaid-svg-sl4ODSvoOnTmtYQW svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-sl4ODSvoOnTmtYQW .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-sl4ODSvoOnTmtYQW .cluster-label text{fill:#333;}#mermaid-svg-sl4ODSvoOnTmtYQW .cluster-label span{color:#333;}#mermaid-svg-sl4ODSvoOnTmtYQW .label text,#mermaid-svg-sl4ODSvoOnTmtYQW span{fill:#333;color:#333;}#mermaid-svg-sl4ODSvoOnTmtYQW .node rect,#mermaid-svg-sl4ODSvoOnTmtYQW .node circle,#mermaid-svg-sl4ODSvoOnTmtYQW .node ellipse,#mermaid-svg-sl4ODSvoOnTmtYQW .node polygon,#mermaid-svg-sl4ODSvoOnTmtYQW .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-sl4ODSvoOnTmtYQW .node .label{text-align:center;}#mermaid-svg-sl4ODSvoOnTmtYQW .node.clickable{cursor:pointer;}#mermaid-svg-sl4ODSvoOnTmtYQW .arrowheadPath{fill:#333333;}#mermaid-svg-sl4ODSvoOnTmtYQW .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-sl4ODSvoOnTmtYQW .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-sl4ODSvoOnTmtYQW .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-sl4ODSvoOnTmtYQW .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-sl4ODSvoOnTmtYQW .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-sl4ODSvoOnTmtYQW .cluster text{fill:#333;}#mermaid-svg-sl4ODSvoOnTmtYQW .cluster span{color:#333;}#mermaid-svg-sl4ODSvoOnTmtYQW div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-sl4ODSvoOnTmtYQW :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}携带 Origin 头合法非法浏览器请求服务端检查 Origin 合法性添加 CORS 响应头不添加 CORS 头浏览器放行请求浏览器拦截请求

    通过这一机制,CORS 在不牺牲安全性的前提下实现了可控的跨域资源共享,成为现代 Web 开发的基石技术。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 服务端配置 CORS解决跨域问题的原理
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!