JavaScript中的跨域请求与CORS机制
字数 1436 2025-11-16 04:35:00

JavaScript中的跨域请求与CORS机制

1. 跨域问题的来源

同源策略(Same-Origin Policy)是浏览器的一种安全机制,它限制一个源的文档或脚本如何与另一个源的资源进行交互。如果两个URL的协议、域名、端口完全相同,则属于同源;否则属于跨域。例如:

  • https://a.comhttps://b.com → 跨域(域名不同)
  • http://a.comhttps://a.com → 跨域(协议不同)
  • a.com:80a.com:8080 → 跨域(端口不同)

同源策略默认阻止跨域读取资源(如通过fetchXMLHttpRequest请求数据),但允许跨域写入(如表单提交、链接跳转)和嵌入(如<script><img>标签)。


2. 常见的跨域解决方案

(1)JSONP(JSON with Padding)

原理:利用<script>标签不受同源策略限制的特性,通过动态创建<script>标签请求一个JS文件,服务器返回一段调用回调函数的JS代码,将数据作为参数传递给回调函数。
示例

function handleResponse(data) {
  console.log("收到数据:", data);
}
// 动态添加<script>标签
const script = document.createElement('script');
script.src = 'https://api.example.com/data?callback=handleResponse';
document.body.appendChild(script);

缺点:仅支持GET请求,缺乏错误处理机制,存在安全风险(如XSS)。

(2)CORS(跨域资源共享)

CORS是W3C标准,允许服务器声明哪些源可以访问其资源。浏览器在发现跨域请求时,会自动添加Origin头,并根据服务器返回的CORS头决定是否允许访问。


3. CORS的详细机制

(1)简单请求(Simple Request)

需同时满足以下条件:

  • 方法为GET、POST、HEAD之一;
  • 头部仅允许以下字段:AcceptAccept-LanguageContent-LanguageContent-Type(值仅限于application/x-www-form-urlencodedmultipart/form-datatext/plain)。

流程

  1. 浏览器直接发送跨域请求,并在Request Headers中自动添加Origin: https://a.com
  2. 服务器检查Origin,若允许访问,则在响应头中包含:
    Access-Control-Allow-Origin: https://a.com  // 或通配符*
    Access-Control-Allow-Credentials: true      // 可选,允许携带Cookie
    
  3. 浏览器检查响应头,若Access-Control-Allow-Origin包含当前源,则允许读取响应。

(2)预检请求(Preflight Request)

不满足简单请求条件的请求(如使用PUT方法或Content-Type: application/json)会先发送一个OPTIONS预检请求。

流程

  1. 浏览器自动发送OPTIONS请求,头部包含:
    Origin: https://a.com
    Access-Control-Request-Method: PUT
    Access-Control-Request-Headers: Content-Type
    
  2. 服务器响应预检请求,返回允许的规则:
    Access-Control-Allow-Origin: https://a.com
    Access-Control-Allow-Methods: GET, POST, PUT
    Access-Control-Allow-Headers: Content-Type
    Access-Control-Max-Age: 86400  // 缓存预检结果的时间(秒)
    
  3. 预检通过后,浏览器才发送实际请求。

4. 实际代码示例

客户端代码(前端)

// 携带Cookie的CORS请求
fetch('https://api.example.com/data', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  credentials: 'include'  // 需服务器设置Access-Control-Allow-Credentials: true
})
.then(response => response.json())
.catch(error => console.error('请求失败:', error));

服务器端代码(Node.js/Express示例)

app.use((req, res, next) => {
  const allowedOrigins = ['https://a.com', 'https://b.com'];
  const origin = req.headers.origin;
  if (allowedOrigins.includes(origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin);
  }
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
  res.setHeader('Access-Control-Allow-Credentials', 'true');
  // 处理预检请求
  if (req.method === 'OPTIONS') {
    return res.sendStatus(200);
  }
  next();
});

5. 注意事项

  • 通配符*与凭证:若响应头包含Access-Control-Allow-Origin: *,则浏览器不允许携带Cookie(credentials: 'include'会失败)。
  • 错误处理:CORS失败时,浏览器会抛出网络错误,需通过try-catch或Promise的catch捕获。
  • 非简单请求的两次请求:实际请求可能被延迟,需注意性能影响。

通过理解CORS的机制,可以安全地实现跨域数据交互,同时避免常见配置错误。

JavaScript中的跨域请求与CORS机制 1. 跨域问题的来源 同源策略(Same-Origin Policy) 是浏览器的一种安全机制,它限制一个源的文档或脚本如何与另一个源的资源进行交互。如果两个URL的 协议、域名、端口 完全相同,则属于同源;否则属于跨域。例如: https://a.com 和 https://b.com → 跨域(域名不同) http://a.com 和 https://a.com → 跨域(协议不同) a.com:80 和 a.com:8080 → 跨域(端口不同) 同源策略默认阻止跨域读取资源(如通过 fetch 或 XMLHttpRequest 请求数据),但允许跨域写入(如表单提交、链接跳转)和嵌入(如 <script> 、 <img> 标签)。 2. 常见的跨域解决方案 (1)JSONP(JSON with Padding) 原理 :利用 <script> 标签不受同源策略限制的特性,通过动态创建 <script> 标签请求一个JS文件,服务器返回一段调用回调函数的JS代码,将数据作为参数传递给回调函数。 示例 : 缺点 :仅支持GET请求,缺乏错误处理机制,存在安全风险(如XSS)。 (2)CORS(跨域资源共享) CORS是W3C标准,允许服务器声明哪些源可以访问其资源。浏览器在发现跨域请求时,会自动添加 Origin 头,并根据服务器返回的CORS头决定是否允许访问。 3. CORS的详细机制 (1)简单请求(Simple Request) 需同时满足以下条件: 方法为GET、POST、HEAD之一; 头部仅允许以下字段: Accept 、 Accept-Language 、 Content-Language 、 Content-Type (值仅限于 application/x-www-form-urlencoded 、 multipart/form-data 、 text/plain )。 流程 : 浏览器直接发送跨域请求,并在 Request Headers 中自动添加 Origin: https://a.com 。 服务器检查 Origin ,若允许访问,则在响应头中包含: 浏览器检查响应头,若 Access-Control-Allow-Origin 包含当前源,则允许读取响应。 (2)预检请求(Preflight Request) 不满足简单请求条件的请求(如使用PUT方法或 Content-Type: application/json )会先发送一个 OPTIONS 预检请求。 流程 : 浏览器自动发送OPTIONS请求,头部包含: 服务器响应预检请求,返回允许的规则: 预检通过后,浏览器才发送实际请求。 4. 实际代码示例 客户端代码(前端) 服务器端代码(Node.js/Express示例) 5. 注意事项 通配符 * 与凭证:若响应头包含 Access-Control-Allow-Origin: * ,则浏览器不允许携带Cookie( credentials: 'include' 会失败)。 错误处理:CORS失败时,浏览器会抛出网络错误,需通过 try-catch 或Promise的 catch 捕获。 非简单请求的两次请求:实际请求可能被延迟,需注意性能影响。 通过理解CORS的机制,可以安全地实现跨域数据交互,同时避免常见配置错误。