兄弟们谁还没被跨域搞到半夜我见过太多人接口明明通了前端却报No Access-Control-Allow-Origin配了代理刷新半天没生效后端也加了CrossOrigin结果还是不行真机跑起来就报错开发环境却好好的……别急问题不在代码很可能在你没重启服务或者路径写错了。一句话总结跨域不是 bug是浏览器给你设的“防火墙”你要做的不是“破解它”而是正确地和它沟通。一、什么叫跨域别听那些教科书简单粗暴地说只要你看不到后端接口返回的数据就可能是跨域。浏览器判断“同源”标准就三种✅ 协议http/https✅ 域名localhost/127.0.0.1/xxx.com✅ 端口8080 / 3000 / 80只要其中任意一个不一样浏览器就认为你是“外人”直接拦住你。举几个例子你就明白了✅ 同源✅ http://localhost:8080 → http://localhost:8080 https://myapp.com → https://myapp.com ❌ 跨域❌ http://localhost:8080 → http://localhost:3000 ← 端口不同 http://localhost → https://localhost ← 协议不同 http://localhost:8080 → http://api.myapp.com ← 域名不同 重点不是“接口通不通”决定跨不跨域而是前端页面在哪决定。比如你本地起的服务跑在8080接口在3000那看8080的页面向3000要数据就跨了。二、开发环境别瞎改先学会用代理90% 的团队都用代理不是因为“有技术”而是因为——不想天天改接口地址。✅ Vue CLI 项目解决办法在根目录建个vue.config.js别放自动文件夹里就放项目根目录。// vue.config.jsmodule.exports{devServer:{proxy:{/api:{// 所有以 /api 开头的请求target:http://192.168.1.100:8088,// 你的后端地址changeOrigin:true,// 关键必须开pathRewrite:{^/api:// 把 /api 去掉转成真实路径}}}}}⚠️ 注意一定要重启服务修改vue.config.js后npm run dev一定要重新启动不然配置不生效。路径/api不要写错你前端写的是api/login就等于访问http://192.168.1.100:8088/login。✅ 举例前端请求/api/login实际发送http://192.168.1.100:8088/login✅ Vite 项目Vue3解决方案现在都用 Vite 了配置也简单// vite.config.jsimport{defineConfig}fromviteimportvuefromvitejs/plugin-vueexportdefaultdefineConfig({plugins:[vue()],server:{proxy:{/api:{target:http://192.168.1.100:8088,changeOrigin:true,rewrite:(path)path.replace(/^\/api/,)}}}})⚠️ 最大坑rewrite是函数不是字符串。别写成rewrite: /api会出错三、生产环境真机跑通才是真本事开发环境通了但放到服务器上就崩你可能以为是跨域其实不是。这年头谁还让前端去改Access-Control-Allow-Origin除非你是后端不然别瞎改。✅ 正确做法让后端来配置跨域最靠谱JavaSpring Boot写法CrossOrigin(originshttps://yourapp.com)// 一定要写具体域名别写 *publicclassUserController{GetMapping(/login)publicResultlogin(){returnResult.success(ok);}}✅ 重点*可以用在测试环境但只要涉及到 Cookie 或 Token必须写具体域名否则浏览器会拒绝。Spring 全局配置推荐ConfigurationpublicclassWebConfigimplementsWebMvcConfigurer{OverridepublicvoidaddCorsMappings(CorsRegistryregistry){registry.addMapping(/api/**).allowedOrigins(https://yourapp.com)// 真实域名.allowedMethods(GET,POST,PUT,DELETE).allowedHeaders(Content-Type,Authorization).allowCredentials(true)// 有 cookies 就开.maxAge(3600);// 缓存 1 小时减少预检请求}} 为什么maxAge要设因为浏览器会先发一个OPTIONS预检请求1 小时内不用再问了性能高。Node.jsExpress写法app.use((req,res,next){res.header(Access-Control-Allow-Origin,https://yourapp.com);res.header(Access-Control-Allow-Methods,GET,POST,PUT,DELETE);res.header(Access-Control-Allow-Headers,Content-Type,Authorization);res.header(Access-Control-Allow-Credentials,true);res.header(Access-Control-Max-Age,3600);if(req.methodOPTIONS){res.sendStatus(200);}else{next();}});⚠️ 注意如果你用了路由中间件app.use要放在路由之前否则不生效。✅ Nginx 反向代理企业级推荐别把跨域问题丢给前端用 Nginx 代理才是王道。server { listen 80; server_name yourdomain.com; location /api/ { proxy_pass http://192.168.1.100:8088/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 关键让 Nginx 返回跨域头 add_header Access-Control-Allow-Origin https://yourdomain.com; add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE; add_header Access-Control-Allow-Headers Content-Type,Authorization; add_header Access-Control-Allow-Credentials true; } # 前端静态资源 location / { root /www/yourapp; try_files $uri $uri/ /index.html; } }✅ 优势完全避开了前端和后端的“互扯皮”所有请求统一管理安全、可控用作生产环境部署稳定、高效四、配置了还是报错这 6 个坑真能气死人我们来点“血泪经验”说几个你绝对遇到过的坑1️⃣ 配置文件改了但没重启服务Vue CLI改了vue.config.js但没npm run dev重启Vite改了vite.config.js但vite没重启Java改了配置类但没重启 Tomcat✅ 真实场景你改了一个CrossOrigin跑半天没用停掉再跑一次就好了。2️⃣ 接口地址写错了没走代理前端写http://localhost:8080/api/login没写/api然后你认为是跨域其实是压根没走代理直接发到8080和3000的前端没关联当然出错。✅ 所以检查你的请求路径是不是以/api开头看下 DevTools 的 Network 里面的请求 URL。3️⃣ 后端只允许 GETPOST 就被拦了你写个POST /login接口返回 403但前端报跨域实际上是后端不支持 POST 方法浏览器就认为你“权限不够”表现像跨域。✅ 检查方法F12 看 Network看响应状态码是不是 403不是 404那就不是跨域问题。4️⃣ 自定义 Header 没放行比如你在请求头加了headers:{Authorization:Bearer xxx,X-Token:abc}后端没在Access-Control-Allow-Headers中声明Authorization浏览器直接拒绝。✅ 解决后端必须加Authorization到允许头列表。5️⃣ 要 Cookie不能用*必须写具体域名// ❌ 错误写法Access-Control-Allow-Origin:*// ✅ 正确写法Access-Control-Allow-Origin:https://yourapp.com 大坑只要带上withCredentials: true如带 CookieAccess-Control-Allow-Origin就不能是*否则浏览器直接拒绝。6️⃣ 接口返回 404 / 500也可能像跨域前端报CORS blocked但实际后端接口压根不存在返回了 404。浏览器看到“没响应”就以为是跨域其实你接口地址写错了。✅ 解决在 Network 里看请求看 Status 是不是 404 / 500不是 200就别往跨域上想。五、终极总结别怕跨域不可怕场景解决方案开发环境用proxy代理别手写全路径生产环境后端配跨域 或 Nginx 代理推荐用 Token/Cookie必须具体域名禁止*响应 404/500检查接口地址不是跨域问题改了配置没生效重启服务别瞎猜
跨域?别慌,90% 的问题都是你配置没重启/写错了
兄弟们谁还没被跨域搞到半夜我见过太多人接口明明通了前端却报No Access-Control-Allow-Origin配了代理刷新半天没生效后端也加了CrossOrigin结果还是不行真机跑起来就报错开发环境却好好的……别急问题不在代码很可能在你没重启服务或者路径写错了。一句话总结跨域不是 bug是浏览器给你设的“防火墙”你要做的不是“破解它”而是正确地和它沟通。一、什么叫跨域别听那些教科书简单粗暴地说只要你看不到后端接口返回的数据就可能是跨域。浏览器判断“同源”标准就三种✅ 协议http/https✅ 域名localhost/127.0.0.1/xxx.com✅ 端口8080 / 3000 / 80只要其中任意一个不一样浏览器就认为你是“外人”直接拦住你。举几个例子你就明白了✅ 同源✅ http://localhost:8080 → http://localhost:8080 https://myapp.com → https://myapp.com ❌ 跨域❌ http://localhost:8080 → http://localhost:3000 ← 端口不同 http://localhost → https://localhost ← 协议不同 http://localhost:8080 → http://api.myapp.com ← 域名不同 重点不是“接口通不通”决定跨不跨域而是前端页面在哪决定。比如你本地起的服务跑在8080接口在3000那看8080的页面向3000要数据就跨了。二、开发环境别瞎改先学会用代理90% 的团队都用代理不是因为“有技术”而是因为——不想天天改接口地址。✅ Vue CLI 项目解决办法在根目录建个vue.config.js别放自动文件夹里就放项目根目录。// vue.config.jsmodule.exports{devServer:{proxy:{/api:{// 所有以 /api 开头的请求target:http://192.168.1.100:8088,// 你的后端地址changeOrigin:true,// 关键必须开pathRewrite:{^/api:// 把 /api 去掉转成真实路径}}}}}⚠️ 注意一定要重启服务修改vue.config.js后npm run dev一定要重新启动不然配置不生效。路径/api不要写错你前端写的是api/login就等于访问http://192.168.1.100:8088/login。✅ 举例前端请求/api/login实际发送http://192.168.1.100:8088/login✅ Vite 项目Vue3解决方案现在都用 Vite 了配置也简单// vite.config.jsimport{defineConfig}fromviteimportvuefromvitejs/plugin-vueexportdefaultdefineConfig({plugins:[vue()],server:{proxy:{/api:{target:http://192.168.1.100:8088,changeOrigin:true,rewrite:(path)path.replace(/^\/api/,)}}}})⚠️ 最大坑rewrite是函数不是字符串。别写成rewrite: /api会出错三、生产环境真机跑通才是真本事开发环境通了但放到服务器上就崩你可能以为是跨域其实不是。这年头谁还让前端去改Access-Control-Allow-Origin除非你是后端不然别瞎改。✅ 正确做法让后端来配置跨域最靠谱JavaSpring Boot写法CrossOrigin(originshttps://yourapp.com)// 一定要写具体域名别写 *publicclassUserController{GetMapping(/login)publicResultlogin(){returnResult.success(ok);}}✅ 重点*可以用在测试环境但只要涉及到 Cookie 或 Token必须写具体域名否则浏览器会拒绝。Spring 全局配置推荐ConfigurationpublicclassWebConfigimplementsWebMvcConfigurer{OverridepublicvoidaddCorsMappings(CorsRegistryregistry){registry.addMapping(/api/**).allowedOrigins(https://yourapp.com)// 真实域名.allowedMethods(GET,POST,PUT,DELETE).allowedHeaders(Content-Type,Authorization).allowCredentials(true)// 有 cookies 就开.maxAge(3600);// 缓存 1 小时减少预检请求}} 为什么maxAge要设因为浏览器会先发一个OPTIONS预检请求1 小时内不用再问了性能高。Node.jsExpress写法app.use((req,res,next){res.header(Access-Control-Allow-Origin,https://yourapp.com);res.header(Access-Control-Allow-Methods,GET,POST,PUT,DELETE);res.header(Access-Control-Allow-Headers,Content-Type,Authorization);res.header(Access-Control-Allow-Credentials,true);res.header(Access-Control-Max-Age,3600);if(req.methodOPTIONS){res.sendStatus(200);}else{next();}});⚠️ 注意如果你用了路由中间件app.use要放在路由之前否则不生效。✅ Nginx 反向代理企业级推荐别把跨域问题丢给前端用 Nginx 代理才是王道。server { listen 80; server_name yourdomain.com; location /api/ { proxy_pass http://192.168.1.100:8088/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 关键让 Nginx 返回跨域头 add_header Access-Control-Allow-Origin https://yourdomain.com; add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE; add_header Access-Control-Allow-Headers Content-Type,Authorization; add_header Access-Control-Allow-Credentials true; } # 前端静态资源 location / { root /www/yourapp; try_files $uri $uri/ /index.html; } }✅ 优势完全避开了前端和后端的“互扯皮”所有请求统一管理安全、可控用作生产环境部署稳定、高效四、配置了还是报错这 6 个坑真能气死人我们来点“血泪经验”说几个你绝对遇到过的坑1️⃣ 配置文件改了但没重启服务Vue CLI改了vue.config.js但没npm run dev重启Vite改了vite.config.js但vite没重启Java改了配置类但没重启 Tomcat✅ 真实场景你改了一个CrossOrigin跑半天没用停掉再跑一次就好了。2️⃣ 接口地址写错了没走代理前端写http://localhost:8080/api/login没写/api然后你认为是跨域其实是压根没走代理直接发到8080和3000的前端没关联当然出错。✅ 所以检查你的请求路径是不是以/api开头看下 DevTools 的 Network 里面的请求 URL。3️⃣ 后端只允许 GETPOST 就被拦了你写个POST /login接口返回 403但前端报跨域实际上是后端不支持 POST 方法浏览器就认为你“权限不够”表现像跨域。✅ 检查方法F12 看 Network看响应状态码是不是 403不是 404那就不是跨域问题。4️⃣ 自定义 Header 没放行比如你在请求头加了headers:{Authorization:Bearer xxx,X-Token:abc}后端没在Access-Control-Allow-Headers中声明Authorization浏览器直接拒绝。✅ 解决后端必须加Authorization到允许头列表。5️⃣ 要 Cookie不能用*必须写具体域名// ❌ 错误写法Access-Control-Allow-Origin:*// ✅ 正确写法Access-Control-Allow-Origin:https://yourapp.com 大坑只要带上withCredentials: true如带 CookieAccess-Control-Allow-Origin就不能是*否则浏览器直接拒绝。6️⃣ 接口返回 404 / 500也可能像跨域前端报CORS blocked但实际后端接口压根不存在返回了 404。浏览器看到“没响应”就以为是跨域其实你接口地址写错了。✅ 解决在 Network 里看请求看 Status 是不是 404 / 500不是 200就别往跨域上想。五、终极总结别怕跨域不可怕场景解决方案开发环境用proxy代理别手写全路径生产环境后端配跨域 或 Nginx 代理推荐用 Token/Cookie必须具体域名禁止*响应 404/500检查接口地址不是跨域问题改了配置没生效重启服务别瞎猜