以下是关于CORS(跨域资源共享)的完整解析及配置指南,结合资料中的关键信息进行系统化阐述:
一、CORS的定义与作用
1. 基本概念
- CORS(Cross-Origin Resource Sharing) 是W3C标准的安全机制,允许浏览器绕过同源策略(Same-Origin Policy, SOP),安全地访问不同源的资源(如API、图片、字体等)。
- 同源策略(SOP) 是浏览器的核心安全机制,默认阻止跨域请求(协议、域名、端口任一不同即视为跨域)。
2. 解决的问题
- 现代Web应用常需跨域访问资源(如前端调用第三方API、CDN共享资源),但SOP会阻止此类请求。CORS通过HTTP头部协商机制,在保持安全的前提下解除限制。
- 典型应用场景:
- HTML5文件拖拽上传至不同源存储服务(如OBS)。
- 跨域加载外部网页、样式表或Web字体。
- 多站点共享同一资源(如图片库)。
二、CORS的工作原理
1. 关键参与者
- 浏览器:自动处理CORS流程(发送预检请求、验证响应头)。
- 服务器:通过响应头声明允许的跨域规则。
2. 请求分类与流程
请求类型 | 触发条件 | 流程步骤 |
---|---|---|
简单请求 | 方法为GET/POST/HEAD,头部为Accept、Content-Type等简单字段 | 1. 浏览器直接发送请求 2. 检查响应头 Access-Control-Allow-Origin 是否匹配 |
预检请求 | 方法为PUT/DELETE或含自定义头部(如Authorization) | 1. 浏览器先发OPTIONS请求(预检) 2. 服务器返回允许的规则 3. 通过后发送实际请求 |
3. 核心HTTP头部
- 请求头:
Origin
:声明请求来源(如[https://example.com](https://example.com)
)。Access-Control-Request-Method
:声明实际请求方法(预检请求携带)。Access-Control-Request-Headers
:声明自定义头部(预检请求携带)。
- 响应头:
Access-Control-Allow-Origin
:允许的源(如[https://example.com](https://example.com)
或*
)。Access-Control-Allow-Methods
:允许的HTTP方法(如GET,POST
)。Access-Control-Allow-Headers
:允许的自定义头部。Access-Control-Allow-Credentials
:是否允许携带凭据(如Cookies)。Access-Control-Max-Age
:预检结果缓存时间(秒)。
示例预检请求/响应:
OPTIONS /api/data HTTP/1.1 Origin: [https://yuanjava.com](https://yuanjava.com) Access-Control-Request-Method: PUT Access-Control-Request-Headers: Content-Type HTTP/1.1 204 No Content Access-Control-Allow-Origin: [https://yuanjava.com](https://yuanjava.com) Access-Control-Allow-Methods: GET, POST, PUT Access-Control-Allow-Headers: Content-Type Access-Control-Allow-Credentials: true Access-Control-Max-Age: 3600
三、CORS的正确配置方法
1. 服务器端配置(关键步骤)
需在资源服务器配置响应头,以下是主流方案:
-
通用配置原则:
- 明确允许的源(避免滥用
*
)。 - 按需开放方法(GET/POST等)和头部。
- 若需凭据(Cookies),设置
Access-Control-Allow-Credentials: true
且禁止使用*
作为源。
- 明确允许的源(避免滥用
-
配置示例:
- Apache服务器(修改
.htaccess
):
- Apache服务器(修改
Header set Access-Control-Allow-Origin "https://your-domain.com"
Header set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header set Access-Control-Allow-Headers "Content-Type, Authorization"
Header set Access-Control-Allow-Credentials "true"
Nginx服务器(修改配置文件):
add_header Access-Control-Allow-Origin "https://your-domain.com";
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'Content-Type, Authorization';
add_header Access-Control-Allow-Credentials 'true';
后端框架示例:
- Spring Boot(Java):
@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("https://your-domain.com")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowCredentials(true)
.maxAge(3600);
}
}
Express(Node.js):
const cors = require('cors');
app.use(cors({
origin: 'https://your-domain.com',
methods: ['GET', 'POST'],
credentials: true
}));
GoFrame(Golang):
// boot.yaml
gf:
interceptors:
cors:
enabled: true
allowOrigins: "https://your-domain.com"
allowMethods: "GET,POST"
2. 客户端注意事项
若请求需携带凭据(如Cookies),前端需显式设置:
fetch('https://api.com/data', {
credentials: 'include' // 或 xhr.withCredentials = true;
});
-
否则浏览器会拒绝跨域凭据请求。
四、常见错误与解决方案
错误现象 | 原因分析 | 解决方案 |
---|---|---|
No 'Access-Control-Allow-Origin' header is present | 服务器未返回Access-Control-Allow-Origin 响应头 | 检查服务器配置,确保该头部存在且值匹配请求源 |
Access-Control-Allow-Origin cannot be '*' when using credentials | 凭据模式下不允许源为通配符* | 指定具体源(如[https://example.com](https://example.com) )并设置Access-Control-Allow-Credentials: true |
CORS preflight channel did not succeed | 预检请求(OPTIONS)未正确处理(如返回非200状态码) | 确保服务器正确响应OPTIONS请求,返回200及CORS头部 |
Method [PUT] not allowed in Access-Control-Allow-Methods | 实际请求方法不在服务器允许的方法列表中 | 在Access-Control-Allow-Methods 中添加缺失方法(如PUT) |
调试建议:
使用浏览器开发者工具查看Network选项卡,分析预检请求(OPTIONS)和实际请求的请求头/响应头,定位缺失或错误的CORS头部。
五、进阶实践与安全建议
- 动态源管理
- 若允许多个源,可编程检查
Origin
请求头,动态设置Access-Control-Allow-Origin
(需避免漏洞)。
- 若允许多个源,可编程检查
- 预检缓存优化
- 设置
Access-Control-Max-Age
减少OPTIONS请求频率(如3600
秒)。
- 设置
- 安全风险规避
- 避免
Access-Control-Allow-Origin: *
:尤其在涉及敏感数据或凭据时。 - 限制HTTP方法:仅开放必要方法(如禁止DELETE)。
- 验证来源域名:防止未授权站点利用CORS。
- 避免
六、总结
CORS是平衡安全性与灵活性的关键技术,其核心在于服务器通过HTTP头部声明跨域规则,由浏览器强制执行。正确配置需关注:
- 区分简单请求与预检请求的处理逻辑。
- 精准设置
Access-Control-Allow-*
系列头部。 - 避免凭据模式下的通配符滥用。
- 结合具体服务器环境(Apache/Nginx/框架)实现配置。
通过理解机制、规范配置和善用调试工具,可高效解决跨域问题。