跨域问题是前端开发中的常见难题,源于JavaScript的同源策略限制。本文深入解析跨域问题的本质原因,详细介绍JSONP、CORS、代理服务器、postMessage等多种跨域解决方案,并提供实际代码示例和配置方法

一、什么是跨域
1.1 域名的组成结构
一个完整的域名地址由以下几个部分组成:
http:// www . google : 8080 / script/jquery.js
详细分解:
1 2 3 4 5
| http:// (协议号/Protocol) www (子域名/Subdomain) google (主域名/Main Domain) 8080 (端口号/Port) script/jquery.js (请求的地址/Path)
|
1.2 跨域的定义
1
| 跨域(Cross-Origin)是指当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同的"域"。不同的域之间相互请求资源,就称为"跨域"。
|
http://www.abc.com/index.html 请求 http://www.def.com/server.php → 跨域http://www.abc.com/index.html 请求 http://www.abc.com/api/data → 同域https://www.abc.com/index.html 请求 http://www.abc.com/api/data → 跨域(协议不同)http://www.abc.com:8080/index.html 请求 http://www.abc.com:9090/api/data → 跨域(端口不同)
1.3 跨域产生的原因
跨域问题源于浏览器的同源策略(Same-Origin Policy,SOP)。同源策略是浏览器实施的一种安全机制,限制当前域名下的JavaScript只能读取同域的窗口属性。
- 当前域名下的JavaScript无法直接访问其他域名的资源
- 无法读取其他域名的Cookie、LocalStorage等数据
- 无法发送跨域的Ajax请求(XMLHttpRequest)
只有当协议、主机名和端口号都完全匹配时,才被认为是同源,可以被授权访问。
1.4 服务器端不存在跨域问题
1
| 重要说明: 跨域是浏览器层面的安全限制,在服务器端不存在跨域之说。
|
- 使用Node.js请求Java后端数据时,即使两个服务的地址不同,这也不是跨域问题
- 跨域只发生在浏览器中,服务器之间的HTTP请求不受同源策略限制
很多项目为了前后端分离,使用Node.js作为中间层。对于浏览器来说,它请求的是同域的Node.js服务,Node.js再转发请求到后端Java服务,这里并没有发生跨域。至于Java后端如何判断请求的合法性(如IP白名单、API签名等),属于服务端安全验证的范畴。
二、跨域解决方案
2.1 JSONP方案
1
| JSONP(JSON with Padding)是一种利用`<script>`标签不受同源策略限制的特性来实现跨域请求的方法。
|
1 2
| 工作原理: 1. 动态创建`<script>`标签,设置`src`属性为目标API地址
|
- 服务器返回的数据包装在回调函数中
- 浏览器执行回调函数,获取数据
- 只支持GET请求
- 安全性较低,容易受到XSS攻击
- 错误处理困难
2.2 CORS方案
CORS(Cross-Origin Resource Sharing)是W3C标准,是目前最主流的跨域解决方案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); } `使用Filter方式:```java
@SpringBootApplication @RestController @EnableSwagger2 @EnableAutoConfiguration @ComponentScan @EnableDiscoveryClient @EnableHystrix public class Application {
@Bean public FilterRegistrationBean securityFilter() { final FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(new SecurityFilter()); registrationBean.addUrlPatterns("/*"); registrationBean.setOrder(Integer.MAX_VALUE); return registrationBean; } `前端HTML页面设置(不推荐,仅作了解):```html <!-- 页面中设置CORS头,但这种方式不推荐使用 --> <meta http-equiv="Access-Control-Allow-Origin" content="*">
|
1
| 注意: HTML的`<meta>`标签方式实际上无法真正解决跨域问题,CORS需要在服务器端配置。
|
2.3 代理服务器方案
通过代理服务器转发请求,将跨域请求转换为同域请求。
- 开发环境: 使用Webpack DevServer的proxy配置
- 生产环境: 使用Nginx反向代理
1 2 3 4 5 6 7 8 9 10
| server { listen 80; server_name localhost; location /api { proxy_pass http://backend-server:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }
|
2.4 postMessage方案
postMessage是HTML5提供的跨窗口通信API,主要用于iframe之间的跨域通信。
- 父页面与iframe子页面之间的通信
- 不同窗口之间的数据传递
1 2 3 4 5 6 7 8 9 10 11
| window.postMessage('数据内容', 'http://target-domain.com');
window.addEventListener('message', function(event) { if (event.origin !== 'http://trusted-domain.com') { return; } console.log('收到消息:', event.data); });
|
三、方案选择建议
- 推荐使用代理服务器方案(Webpack DevServer proxy)
- 简单快速,无需修改后端代码
- 推荐使用CORS方案
- 标准规范,安全性高,支持所有HTTP方法
- 需要在服务器端正确配置
- 需要支持老版本浏览器:考虑JSONP方案
- iframe跨域通信:使用postMessage方案
四、安全注意事项
CORS配置安全:
1
| - 生产环境不要使用`allowedOrigins("*")`,应指定具体的域名
|
- 合理设置
allowedMethods和allowedHeaders - 对于需要携带Cookie的请求,确保
allowCredentials为true且allowedOrigins不能为*
JSONP安全:
- 验证回调函数名,防止XSS攻击
- 对返回的数据进行转义处理
代理服务器安全:
1 2 3
| - [跨域总结--JSONP,CORS,postMessage,子域名代理](http://m.imooc.com/article/19257) - [MDN - CORS](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS) - [W3C CORS规范](https://www.w3.org/TR/cors/)
|
本文标题: Ajax跨域问题解决方案
发布时间: 2019年01月07日 00:00
最后更新: 2025年12月30日 08:54
原始链接: https://haoxiang.eu.org/3047a232/
版权声明: 本文著作权归作者所有,均采用CC BY-NC-SA 4.0许可协议,转载请注明出处!