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

Ajax

一、什么是跨域

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)是指当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同的"域"。不同的域之间相互请求资源,就称为"跨域"
1
示例:
  • 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只能读取同域的窗口属性。

1
同源策略的限制:
  • 当前域名下的JavaScript无法直接访问其他域名的资源
  • 无法读取其他域名的Cookie、LocalStorage等数据
  • 无法发送跨域的Ajax请求(XMLHttpRequest)
1
同源的定义:

只有当协议、主机名和端口号都完全匹配时,才被认为是同源,可以被授权访问。

1.4 服务器端不存在跨域问题

1
重要说明: 跨域是浏览器层面的安全限制,在服务器端不存在跨域之说。
1
示例场景:
  • 使用Node.js请求Java后端数据时,即使两个服务的地址不同,这也不是跨域问题
  • 跨域只发生在浏览器中,服务器之间的HTTP请求不受同源策略限制
1
前后端分离架构中的跨域处理:

很多项目为了前后端分离,使用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地址
  1. 服务器返回的数据包装在回调函数中
  2. 浏览器执行回调函数,获取数据
1
优点:
  • 兼容性好,支持老版本浏览器
  • 实现简单
1
缺点:
  • 只支持GET请求
  • 安全性较低,容易受到XSS攻击
  • 错误处理困难

2.2 CORS方案

CORS(Cross-Origin Resource Sharing)是W3C标准,是目前最主流的跨域解决方案。

1
服务端配置示例(Spring Boot):
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
/**
* CORS配置类
*/
@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
/**
* Application.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 代理服务器方案

通过代理服务器转发请求,将跨域请求转换为同域请求。

1
实现方式:
  • 开发环境: 使用Webpack DevServer的proxy配置
  • 生产环境: 使用Nginx反向代理
1
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之间的跨域通信。

1
使用场景:
  • 父页面与iframe子页面之间的通信
  • 不同窗口之间的数据传递
1
示例代码:
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);
});

三、方案选择建议

1
开发环境:
  • 推荐使用代理服务器方案(Webpack DevServer proxy)
  • 简单快速,无需修改后端代码
1
生产环境:
  • 推荐使用CORS方案
  • 标准规范,安全性高,支持所有HTTP方法
  • 需要在服务器端正确配置
1
特殊场景:
  • 需要支持老版本浏览器:考虑JSONP方案
  • iframe跨域通信:使用postMessage方案

四、安全注意事项

  1. CORS配置安全:

    1
    - 生产环境不要使用`allowedOrigins("*")`,应指定具体的域名
    • 合理设置allowedMethodsallowedHeaders
    • 对于需要携带Cookie的请求,确保allowCredentials为true且allowedOrigins不能为*
  2. JSONP安全:

    • 验证回调函数名,防止XSS攻击
    • 对返回的数据进行转义处理
  3. 代理服务器安全:

    • 配置适当的访问控制
    • 验证请求来源,防止恶意请求
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许可协议,转载请注明出处!

× 喜欢就赞赏一下呗!
打赏二维码