HTML跨域资源共享 (CORS)
HTML跨域资源共享 (CORS)[编辑 | 编辑源代码]
跨域资源共享(Cross-Origin Resource Sharing,简称CORS)是一种基于HTTP头的机制,允许服务器指示浏览器允许或拒绝来自不同源(域、协议或端口)的网页请求。它是现代Web开发中处理跨域请求的标准方式。
介绍[编辑 | 编辑源代码]
在Web开发中,出于安全考虑,浏览器会实施同源策略(Same-Origin Policy),限制来自不同源的脚本与资源交互。CORS提供了一种安全的方式,允许服务器声明哪些外部源可以访问其资源。
为什么需要CORS[编辑 | 编辑源代码]
- 现代Web应用常常需要从多个域加载资源(如API、字体、图像)
- 同源策略会阻止这些合法的跨域请求
- CORS提供了一种标准化的方式来解决这个问题
基本概念[编辑 | 编辑源代码]
同源与不同源[编辑 | 编辑源代码]
两个URL在以下情况下被认为是同源:
- 相同的协议(http/https)
- 相同的主机名(domain)
- 相同的端口号
例如:
https://example.com/page1
和https://example.com/page2
- 同源https://example.com
和http://example.com
- 不同源(协议不同)https://example.com
和https://api.example.com
- 不同源(主机名不同)
CORS工作原理[编辑 | 编辑源代码]
CORS通过HTTP头来实现跨域请求的控制。以下是CORS的基本流程:
简单请求[编辑 | 编辑源代码]
满足以下条件的请求被视为简单请求: 1. 使用GET、HEAD或POST方法 2. 仅包含安全的头(Accept、Accept-Language、Content-Language等) 3. Content-Type为application/x-www-form-urlencoded、multipart/form-data或text/plain
示例:
fetch('https://api.example.com/data', {
method: 'GET',
headers: {
'Content-Type': 'text/plain'
}
})
.then(response => response.json())
.then(data => console.log(data));
预检请求[编辑 | 编辑源代码]
不满足简单请求条件的请求会先发送一个OPTIONS方法的预检请求(Preflight Request),服务器确认允许后才会发送实际请求。
示例:
fetch('https://api.example.com/data', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-Custom-Header': 'value'
},
body: JSON.stringify({key: 'value'})
});
HTTP头详解[编辑 | 编辑源代码]
以下是CORS相关的主要HTTP头:
请求头[编辑 | 编辑源代码]
- Origin: 指示请求的来源
- Access-Control-Request-Method: 预检请求中声明实际请求的方法
- Access-Control-Request-Headers: 预检请求中声明实际请求的自定义头
响应头[编辑 | 编辑源代码]
- Access-Control-Allow-Origin: 指定允许访问资源的源
- Access-Control-Allow-Methods: 指定允许的方法
- Access-Control-Allow-Headers: 指定允许的头
- Access-Control-Allow-Credentials: 指定是否允许发送凭据
- Access-Control-Max-Age: 指定预检请求的缓存时间
服务器配置示例[编辑 | 编辑源代码]
Node.js (Express)[编辑 | 编辑源代码]
const express = require('express');
const app = express();
// 基本CORS配置
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
});
// 带凭证的CORS配置
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://trusted.example.com');
res.header('Access-Control-Allow-Credentials', 'true');
next();
});
PHP[编辑 | 编辑源代码]
<?php
header("Access-Control-Allow-Origin: https://trusted.example.com");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type");
?>
实际应用场景[编辑 | 编辑源代码]
场景1:跨域API调用[编辑 | 编辑源代码]
前端应用(https://app.example.com
)需要调用API(https://api.example.com
)
场景2:CDN资源访问[编辑 | 编辑源代码]
主站(https://www.example.com
)需要从CDN(https://cdn.example.net
)加载字体或脚本
场景3:微服务架构[编辑 | 编辑源代码]
多个服务部署在不同子域下需要相互通信
安全注意事项[编辑 | 编辑源代码]
- 谨慎使用
Access-Control-Allow-Origin: *
,特别是涉及敏感数据时 - 对于需要凭证的请求,必须指定具体的源而非通配符
- 限制允许的方法和头,遵循最小权限原则
- 考虑使用CSRF令牌等额外安全措施
常见问题[编辑 | 编辑源代码]
如何解决CORS错误?[编辑 | 编辑源代码]
1. 检查服务器是否正确设置了CORS头
2. 确保请求符合简单请求条件或正确处理了预检请求
3. 对于需要凭证的请求,设置credentials: 'include'
(fetch API)或withCredentials: true
(XHR)
JSONP与CORS有什么区别?[编辑 | 编辑源代码]
JSONP是早期解决跨域问题的技术,只支持GET请求,安全性较差。CORS是更现代、更安全的解决方案,支持所有HTTP方法。
高级主题[编辑 | 编辑源代码]
credentialed请求[编辑 | 编辑源代码]
需要发送cookie或HTTP认证信息的请求必须:
- 服务器设置
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin
不能为*
- 客户端设置withCredentials标志
预检请求缓存[编辑 | 编辑源代码]
通过Access-Control-Max-Age
头可以减少不必要的预检请求。
总结[编辑 | 编辑源代码]
CORS是现代Web开发中处理跨域请求的标准机制。理解CORS的工作原理和配置方法对于开发需要跨域资源访问的Web应用至关重要。正确配置CORS既能满足功能需求,又能保障应用安全性。