CORS解决方案汇总
字数 967 2025-08-18 17:33:11
CORS跨域资源共享安全配置指南
1. CORS基础概念
1.1 CORS定义
CORS全称"跨域资源共享"(Cross-origin resource sharing),是一种用于绕过SOP(同源策略)来实现跨域资源访问的技术。
1.2 CORS与SOP的关系
- SOP(同源策略)限制了网页的业务需求,不能使不同域的网页互相访问
- CORS的出现是为了弥补SOP的不足
1.3 CORS漏洞
攻击者利用CORS技术获取用户敏感数据,导致信息泄露的安全问题。
2. CORS漏洞验证方法
使用curl命令验证CORS配置:
curl -vv -H "Origin: http://hack${你的域名}" http://${你的域名}
示例:
curl -vv -H "Origin: http://hackbaidu.com" http://xxxx.baidu.com
判断标准:
- 如果
Access-Control-Allow-Origin返回*或http://hackbaidu.com,则存在漏洞 - 如果未返回
Access-Control-Allow-Origin头,则不存在漏洞
3. CORS安全配置方案
3.1 代码层面配置
3.1.1 单个Controller配置(Spring框架)
@CrossOrigin(origins = {"http://localhost:9000", "http://www.baidu.com"})
@RequestMapping("/testCors.do")
public @ResponseBody String CORSTest(HttpServletRequest request, HttpServletResponse response) {
String map = "no_pass";
String origin = request.getHeader("Origin");
if(origin != null){
String safeOrigin = SecurityUtil.getSafeUrl(origin);
if(safeOrigin != null){
map = "pass";
response.setHeader("Access-Control-Allow-Origin", safeOrigin);
response.setContentType("application/json;charset=UTF-8");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("XDomainRequestAllowed","1");
} else{
map = "checked_no_pass";
}
} else{
map = "pass";
}
return map;
}
关键点:
- 不允许使用通配符
*配置 - 只设置需要跨域的接口
- 对origin来源进行严格验证
3.1.2 全局Controller配置
方式一:Java Bean注解配置
@Configuration
public class MyConfiguration {
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://domain1.com");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
}
方式二:XML配置
<!-- support cors-->
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,xsrf-token</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>www.test.com</url-pattern>
</filter-mapping>
3.2 Nginx配置方案
set $cors_origin "";
if ($http_origin ~* "^http://127.0.0.1$") {
set $cors_origin $http_origin;
}
if ($http_origin ~* "^http://localhost$") {
set $cors_origin $http_origin;
}
add_header Access-Control-Allow-Origin $cors_origin;
location / {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin $cors_origin;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
return 204;
}
}
注意事项:
- 不要同时在Nginx和后端代码中配置CORS,会导致跨域配置失败
- 浏览器会收到两个
Access-Control-Allow-Origin头,导致错误
3.3 Kubernetes Ingress配置(YAML方案)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/configuration-snippet: |
set $allow_cors "";
if ($http_origin ~ "^https?://([a-zA-Z0-9.-]+\.)?test\.com(:\d+)?$") {
set $allow_cors "true";
}
more_set_headers 'Access-Control-Allow-Origin: $allow_cors';
spec:
rules:
- host: your.host.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: your-service-name
port:
name: http
4. 跨域测试方案
在浏览器开发者控制台执行以下JavaScript代码测试:
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.xxx.com/api/action');
xhr.send(null);
xhr.onload = function(e) {
var xhr = e.target;
console.log(xhr.responseText);
}
结果分析:
- 请求超时:网络不通或地址无效
- 正常返回:支持跨域
- 返回错误:不支持跨域
5. 安全配置最佳实践
-
白名单原则:
- 只设置企业内部需要的域名
- 不允许使用通配符
*配置 - 具体域名不使用任何通配符(如
*.test.com一级域名不能被统配)
-
配置层级选择:
- 只在一个地方配置CORS(Nginx或后端代码)
- 避免多层配置导致冲突
-
敏感接口保护:
- CORS和JSONP接口不开放给外部调用
- 白名单内只设置企业内部域名
-
黑白盒结合测试:
- 代码扫描可能无法发现Nginx层的配置问题
- 必须进行黑盒测试验证实际效果