写点什么

解决跨域问题的这 6 种方案,真香!

  • 2025-03-05
    福建
  • 本文字数:2759 字

    阅读完需:约 9 分钟

解决跨域问题的这6种方案,真香!

1 什么事跨域问题?

很多小伙伴第一次遇到跨域问题,大概率会一脸懵逼:“我后端接口明明通了,Postman 也能调,为啥浏览器就报红字?”



其实这事儿得怪浏览器的“同源策略”(Same-Origin Policy)。

简单说,浏览器觉得“不同源的请求都是耍流氓”。

比如你的前端跑在 http://localhost:8080。

而后端在https://api.xxx.com:8000

只要协议域名端口任何一个不同,就会被浏览器直接掐断。

举个栗子🌰:

// 前端代码(http://localhost:8080)fetch('http://api.xxx.com:8000/user')  .then(res => res.json())  .then(data => console.log(data));  // 浏览器控制台报错:  // Access to fetch from 'http://localhost:8080' has been blocked by CORS policy...
复制代码

这时候,你就需要“跨域解决方案”来帮浏览器松绑了!

那么,如何解决跨域问题呢?

2 解决跨域问题的方案

2.1 CORS(跨域资源共享)

适用场景:前后端分离项目、接口需要兼容多种客户端。

CORS 是 W3C 标准,后端只需在响应头里加几个字段,告诉浏览器“这个接口我允许谁访问”

后端代码示例(Spring Boot 版)

// 方法1:直接怼注解(适合单个接口)@CrossOrigin(origins = "http://localhost:8080")@GetMapping("/user")public User getUser() { ... }
// 方法2:全局配置(一劳永逸)@Configurationpublic class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:8080") .allowedMethods("*") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); }}
复制代码

关键响应头

  • Access-Control-Allow-Origin: http://localhost:8080(允许的源)

  • Access-Control-Allow-Methods: GET,POST(允许的方法)

  • Access-Control-Allow-Credentials: true(允许带 Cookie)

注意坑点

  • 如果用了allowCredentials(true)allowedOrigins不能为*(必须明确指定域名)。

  • 复杂请求(比如 Content-Type 是application/json)会先发一个 OPTIONS 预检请求,记得处理!

2.2 JSONP

适用场景:老项目兼容、只支持 GET 请求(比如调用第三方地图 API)。

JSONP 利用<script>标签没有跨域限制的特性,让后端返回一段 JS 代码。

前端代码

function handleUserData(data) {    console.log("收到数据:", data);}
// 动态创建script标签const script = document.createElement('script');script.src = 'http://api.xxx.com:8000/user?callback=handleUserData';document.body.appendChild(script);
复制代码

后端代码

@GetMapping("/user")public String jsonp(@RequestParam String callback) {    User user = new User("Tony", 30);    // 把数据包进回调函数里    return callback + "(" + new Gson().toJson(user) + ")";}
复制代码

输出结果

handleUserData({"name":"Tony","age":30})  
复制代码

缺点

  • 只支持 GET(传参长度有限)。

  • 容易被 XSS 攻击(毕竟得信任第三方脚本)。

2.3 Nginx 反向代理

适用场景:生产环境部署、微服务网关统一处理。

直接把跨域问题甩给 Nginx,让浏览器以为所有请求都是同源的。

Nginx 配置示例

server {    listen 80;    server_name localhost;
location /api { # 转发到真实后端 proxy_pass http://api.xxx.com:8000; # 解决跨域 add_header 'Access-Control-Allow-Origin' 'http://localhost:8080'; add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS'; add_header 'Access-Control-Allow-Headers' 'Content-Type'; }}
复制代码

此时前端请求地址改成同源

fetch('/api/user')  // 实际访问 http://localhost/api/user → 被Nginx转发
复制代码

优点

  • 前后端代码零侵入。

  • 能隐藏真实接口地址(安全加分)。

2.4 网关层统一处理

适用场景:Spring Cloud Gateway、Kong 等 API 网关。

和 Nginx 思路类似,但更适合微服务场景,直接在网关层加 CORS 配置。

Spring Cloud Gateway 配置

spring:  cloud:    gateway:      globalcors:        cors-configurations:          '[/**]':            allowed-origins: "http://localhost:8080"            allowed-methods: "*"            allowed-headers: "*"            allow-credentials: true
复制代码

2.5 WebSocket

适用场景:实时通信需求(聊天室、股票行情)。

WebSocket 协议没有跨域限制(因为握手阶段走 HTTP,后续升级为长连接)。

前端代码

const socket = new WebSocket('ws://api.xxx.com:8000/ws');socket.onmessage = (event) => {    console.log('收到消息:', event.data);};
复制代码

后端代码(Spring Boot)

@Configuration@EnableWebSocketpublic class WebSocketConfig implements WebSocketConfigurer {    @Override    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {        registry.addHandler(new MyWebSocketHandler(), "/ws");    }}
复制代码

2.6 PostMessage

适用场景:页面与 iframe、弹窗之间的跨域通信。

通过window.postMessage实现不同窗口间的数据传递。

父页面(http://parent.com

const childWindow = window.open('http://child.com');childWindow.postMessage('我是你爹', 'http://child.com');
复制代码

子页面(http://child.com

window.addEventListener('message', (event) => {    if (event.origin !== 'http://parent.com') return; // 验证来源    console.log('收到爹的消息:', event.data);});
复制代码

总结

  • 简单粗暴:开发环境用 CORS 注解。

  • 生产环境:优先 Nginx/网关统一处理,避免每个服务配一遍。

  • 老项目兼容:JSONP 勉强能用,但别长期依赖。

  • 实时场景:直接上 WebSocket,顺便解决通信问题。

  • 安全第一Access-Control-Allow-Origin尽量别写*,白名单要用精确域名。

最后提醒温馨提醒一下:跨域问题本质是浏览器行为,和 HTTP 协议无关。

如果你用 Postman,发送 curl 请求,测试没问题,但浏览器报错,别怀疑人生,这可能是前端的锅!

转载出处:https://www.cnblogs.com/12lisu/p/18744568

行业拓展

分享一个面向研发人群使用的前后端分离的低代码软件——JNPF,适配国产化,支持主流数据库和操作系统。

提供五十几种高频预制组件,包括表格、图表、列表、容器、表单等,内置常用的后台管理系统使用场景和基本需求,配置了流程引擎、表单引擎、报表引擎、图表引擎、接口引擎、门户引擎、组织用户引擎等可视化功能引擎,超过数百种功能控件以及大量实用模板,使得在拖拉拽的简单操作下,也能完成开发。

对于工程师来说,灵活的使用高质量预制组件可以极大的节省时间,将更多精力花费在更有创造性和建设性的代码上。

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
解决跨域问题的这6种方案,真香!_伤感汤姆布利柏_InfoQ写作社区