Skip to content

P74 什么是跨域以及如何解决? ​

面试题:什么是跨域?浏览器为什么限制跨域?怎么解决?

1. 什么是跨域 ​

浏览器同源策略(Same-Origin Policy):只有协议 + 域名 + 端口三者都相同才叫"同源"。任一不同就是跨域:

text
http://a.com:8080/api  →  http://b.com/api    跨域(域名不同)
http://a.com/api       →  https://a.com/api   跨域(协议不同)
http://a.com:8080/api  →  http://a.com:9090/api 跨域(端口不同)

同源策略限制:跨域请求的响应不能被页面读取(Cookie、localStorage 也按源隔离),防止恶意网站窃取数据。

注意:跨域限制是浏览器的行为,服务端之间调用没有这个限制。

2. 常见解决方案 ​

① CORS(跨域资源共享,最标准) ​

服务端返回响应头:

http
Access-Control-Allow-Origin: https://a.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true   # 允许携带 Cookie

Spring 里:

java
@CrossOrigin(origins = "https://a.com")
// 或 WebMvcConfigurer 全局配置

复杂请求(非简单请求)会先发 OPTIONS 预检,服务端要处理。

② Nginx 反向代理(最常用) ​

把跨域转成同源:前端只请求同域地址,Nginx 转发到后端:

nginx
location /api/ {
    proxy_pass http://backend:8080/;
}

前端访问 同域/api/xxx,浏览器眼里没有跨域。

③ JSONP(老方案,仅 GET) ​

利用 <script> 标签不受同源限制,动态加载回调函数;只支持 GET,已基本被 CORS 取代。

④ postMessage / 代理 ​

iframe 跨域通信用 window.postMessage;开发环境用 Webpack devServer 代理。

3. 加分点 ​

  • 说出 CORS 预检(preflight)机制:非简单请求先 OPTIONS 确认;
  • 提"Cookie 跨域要 withCredentials + Allow-Credentials,且不能 * 通配源";
  • 网关/微服务统一解决:在网关层配 CORS,服务端不再各自处理;
  • 追问"同源策略防什么":防 CSRF 数据读取、防恶意站点读你的登录态数据。

一句话总结 ​

跨域是浏览器的同源策略限制(协议/域名/端口不同即跨域);解决:CORS 响应头(标准)、Nginx 反向代理(把跨域变同源,最常用)、JSONP(仅 GET)等;微服务在网关统一配 CORS。

基于 VitePress 重建