什么是跨域问题?
跨域问题 是指浏览器出于安全考虑,限制了从一个源(Origin)加载的网页脚本或资源与另一个源的资源进行交互的行为。这种限制是由浏览器的 同源策略(Same-Origin Policy) 引起的。
“跨域”指的是浏览器尝试访问的资源与当前页面的 源(Origin) 不一致。源 由以下三部分组成:
- 协议(Protocol):如
http
、https
。 - 域名(Domain):如
example.com
。 - 端口(Port):如
80
、443
(默认端口可以省略)。
如果两个 URL 的协议、域名和端口完全相同,则它们是 同源;否则就是 跨源(Cross-Origin)。
示例:
https://example.com
和https://example.com/api
是同源。https://example.com
和http://example.com
是跨源(协议不同)。https://example.com
和https://api.example.com
是跨源(域名不同)。https://example.com
和https://example.com:8080
是跨源(端口不同)。
跨域问题主要体现在以下场景中:
(1)AJAX 请求被阻止
- 当使用
XMLHttpRequest
或Fetch API
发起跨域请求时,浏览器会阻止请求,除非服务器明确允许。 - 例如:前端页面在
https://example.com
下,尝试请求https://api.example.com
的数据时,会被浏览器阻止。
(2)Cookie 和 LocalStorage 无法访问
- 浏览器不允许脚本访问跨域的 Cookie 或 LocalStorage 数据。
- 例如:
https://example.com
无法读取https://another.com
的 Cookie。
(3)DOM 操作受限
- 浏览器不允许脚本访问跨域 iframe 的内容。
- 例如:
https://example.com
页面中嵌入了一个https://another.com
的 iframe,脚本无法访问 iframe 中的 DOM。
(4)Web Fonts 和图片加载受限
- 某些资源(如字体、图片)的跨域加载可能会受到限制,除非服务器设置正确的 CORS 头。
为什么要有同源策略限制?
1. 防止数据泄露
- 如果没有同源策略,恶意网站可以通过脚本访问其他网站的数据(如 Cookie、LocalStorage),导致用户隐私泄露。
- 例如:用户在
https://bank.com
登录后,访问了恶意网站https://evil.com
,如果没有同源策略,evil.com
可以读取bank.com
的 Cookie,从而窃取用户的银行账户信息。
2. 防止 CSRF(跨站请求伪造)攻击
- 同源策略可以防止恶意网站伪造用户请求,执行未经授权的操作。
- 例如:用户在
https://bank.com
登录后,访问了恶意网站https://evil.com
,evil.com
可以伪造一个请求到https://bank.com/transfer
,将用户的资金转走。同源策略可以阻止这种行为。
3. 防止恶意脚本注入
- 同源策略可以防止恶意脚本通过 iframe 或 AJAX 请求访问其他网站的内容。
- 例如:如果没有同源策略,恶意网站可以通过 iframe 嵌入
https://mail.com
,并窃取用户的邮件内容。
4. 保护用户隐私
- 同源策略可以防止网站通过脚本获取用户的浏览历史、本地存储数据等隐私信息。
如何解决跨域问题?
常见的跨域解决方案包括:
(1)CORS(跨域资源共享)
CORS 是官方推荐的跨域解决方案。它通过在 服务器端设置 HTTP 响应头,明确告诉浏览器允许哪些来源、方法和头部的跨域请求。
服务器端配置示例:
// Spring Boot 中的 CORS 配置
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 允许所有路径的跨域请求
.allowedOriginPatterns("*") // 允许所有来源
.allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的请求方法
.allowedHeaders("*") // 允许的请求头
.allowCredentials(true) // 是否允许带认证信息
.maxAge(3600); // 预检请求的缓存时间
}
- 浏览器在发起跨域请求时,会先发送一个 预检请求(Preflight Request),询问服务器是否允许跨域请求。
- 服务器通过设置
Access-Control-Allow-Origin
等响应头,明确告诉浏览器允许跨域请求。 - 浏览器收到响应后,会根据响应头决定是否允许实际的请求。
(2)JSONP
JSONP 是一种利用 <script>
标签不受同源策略限制的特性来实现跨域请求的技术。
<script>
标签不受同源策略限制,可以加载跨域的 JavaScript 文件。- 服务器返回的数据被包裹在一个回调函数中(如
handleResponse
),前端通过定义这个回调函数来处理数据。 - 缺点是 只支持 GET 请求,且安全性较低(无法处理错误和复杂的请求)。
特性 | <script> 标签的跨域加载 | 同源策略的作用 |
---|---|---|
跨域加载 JavaScript | 可以 | 不限制 <script> 标签的跨域加载,但限制了其他行为(如 AJAX 请求、Cookie 访问)。 |
跨域 AJAX 请求 | 不可以 | 阻止恶意网站通过 AJAX 请求访问其他网站的数据。 |
跨域访问 Cookie | 不可以 | 阻止恶意网站访问其他网站的 Cookie 和 LocalStorage。 |
跨域 DOM 操作 | 不可以 | 阻止恶意网站通过 iframe 嵌入其他网站并操作其 DOM。 |
跨域资源访问 | 部分可以(如 JavaScript 文件) | 阻止恶意网站滥用其他网站的资源(如字体、图片)。 |
(3)代理服务器
代理服务器的原理是让前端请求同源服务器,由同源服务器转发请求到目标服务器。
- 浏览器只向同源服务器发起请求,避免了跨域问题。
- 代理服务器将请求转发到目标服务器,并将响应返回给浏览器。
- 由于代理服务器是服务器之间的通信,不受浏览器的同源策略限制。
(4)WebSocket
WebSocket 是一种全双工通信协议,不受同源策略限制。
- WebSocket 协议本身不受同源策略限制。
- 它适用于实时通信场景(如聊天室、实时数据推送)。
(5)修改浏览器设置(不推荐)
在开发环境中,可以禁用浏览器的同源策略。
- 禁用同源策略后,浏览器不再检查跨域请求,所有请求都会被允许。
- 缺点:这会降低浏览器的安全性,容易受到恶意网站的攻击,因此 不推荐在生产环境中使用。
个人总结
跨域问题主要就是浏览器出于安全的限制,如果在开发过程中遇到了需要跨域的情况,开发者就需要自行进行配置。可以从前端入手设置代理服务器避免出现跨域,也可以从后端入手配置CORS跨域资源共享解决。