Vue3 项目里遇到跨域问题该咋解决?
做Vue3项目的时候,不少同学会碰到接口请求被浏览器拦截、控制台报CORS错误的情况,这就是跨域问题在捣乱啦,跨域咋产生的?Vue3里到底该咋解决?接下来咱们一步步把这些事儿掰碎了说。
先搞懂“跨域”到底是啥?
浏览器为了安全,有个同源策略的规则——只有当网页的协议、域名、端口都和请求的接口一致时,才能正常发请求,要是有一个不一样,比如本地Vue项目跑在localhost:5173
,后端接口在https://api.xxx.com
,协议、域名、端口都对不上,浏览器就会拦截请求,这就是跨域。
Vue3 开发时为啥容易碰到跨域?
开发阶段,前端项目一般用Vite或者Vue CLI启动本地服务(比如Vite默认跑在5173
端口),但后端服务可能部署在另一个域名、另一个端口,甚至另一个服务器上,这时候前端发请求,域名/端口和后端对不上,跨域问题就冒出来了。
开发阶段咋解决跨域?(代理是关键!)
开发时不想让浏览器拦请求,最方便的办法是本地代理——让前端请求先发给本地服务,再由本地服务转发给后端,这样浏览器会觉得是“同源请求”,就不拦截了。
Vite 项目配置代理(改vite.config.js
)
Vite里配代理很简单,在vite.config.js
里加server.proxy
:
import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' export default defineConfig({ plugins: [vue()], server: { proxy: { // 匹配以 /api 开头的请求 '/api': { target: 'https://xxx.com', // 后端真实接口地址 changeOrigin: true, // 把请求头里的Origin改成target的地址(骗后端是同源请求) rewrite: (path) => path.replace(/^\/api/, '') // 把请求路径里的 /api 前缀去掉(后端接口没这个前缀时用) } } } })
举个例子:前端用axios.get('/api/user')
发请求,Vite会把请求转发到https://xxx.com/user
,绕开浏览器的跨域拦截。
Vue CLI 项目配置代理(改vue.config.js
)
如果用Vue CLI创建的项目,就在vue.config.js
里配devServer.proxy
:
module.exports = { devServer: { proxy: { '/api': { target: 'https://xxx.com', // 后端地址 changeOrigin: true, // 开启跨域 pathRewrite: { '^/api': '' } // 去掉 /api 前缀 } } } }
原理和Vite一样,都是让本地服务帮我们转发请求,骗过浏览器的同源策略。
生产环境咋处理跨域?
开发时的代理只适合本地用,线上部署后,前端和后端已经不在同一个“本地服务”了,这时候得换思路:要么让后端开CORS权限,要么用反向代理。
让后端配置CORS响应头
后端服务主动告诉浏览器:“允许这个前端域名来请求我!” 具体咋配?看后端语言:
-
Node.js(Express框架):
加中间件统一处理响应头:const express = require('express'); const app = express(); // 全局允许跨域(生产环境建议指定具体前端域名,别直接用*) app.use((req, res, next) => { res.setHeader('Access-Control-Allow-Origin', 'https://www.xxx.com'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE'); // 允许的请求方法 res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); // 允许的请求头 next(); });
-
Java(Spring Boot):
可以用@CrossOrigin
注解(局部接口允许跨域),或者写全局配置类:import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") // 所有接口 .allowedOrigins("https://www.xxx.com") // 允许的前端域名 .allowedMethods("GET", "POST", "PUT", "DELETE") .allowedHeaders("*") .allowCredentials(true); // 允许带Cookie } }
后端配好后,浏览器收到响应头里的Access-Control-Allow-Origin
,就会允许前端跨域请求了。
用反向代理(Nginx/Apache)
要是不想改后端代码,还能让服务器当“中间人”,比如用Nginx配置反向代理:
server { listen 80; server_name www.xxx.com; # 前端部署的域名 # 处理接口请求的反向代理 location /api { proxy_pass https://api.xxx.com; # 后端接口的真实域名 add_header Access-Control-Allow-Origin *; # 允许所有域名跨域(生产建议指定) add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE'; add_header Access-Control-Allow-Headers 'Content-Type, Authorization'; } # 处理前端静态资源(比如打包后的dist文件) location / { root /usr/share/nginx/html; # 前端静态文件存放路径 index index.html; } }
这样前端请求www.xxx.com/api/user
时,Nginx会转发到后端https://api.xxx.com/user
,同时给响应头加CORS权限,实现跨域。
跨域解决时的常见坑点
就算知道方法,实操时也可能掉坑里,这些细节得注意:
代理配置后请求404?
检查这两点:
target
地址对不对?比如后端接口是不是https://xxx.com
,有没有少写路径?rewrite
或pathRewrite
有没有把前缀处理对?比如后端接口本身就有/api
前缀,那前端请求/api/user
时,代理就不该去掉/api
,否则会变成请求https://xxx.com/user
,导致404。
生产环境CORS配置后还是报错?
- 别把
Access-Control-Allow-Origin
设为(星号)!如果前端请求带Cookie,是不允许的,得改成具体前端域名。 - 后端有没有处理OPTIONS预检请求?有些复杂请求(比如带自定义头、PUT/DELETE方法),浏览器会先发OPTIONS请求探路,后端得返回200并带上CORS头,否则会报错。
带Cookie的跨域请求咋处理?
前端用axios时,要加withCredentials: true
:
axios.get('/api/user', { withCredentials: true });
后端也要配Access-Control-Allow-Credentials: true
,同时Access-Control-Allow-Origin
不能是,得写具体前端域名。
总结解决思路
跨域问题本质是浏览器的安全限制,解决思路分场景:
- 开发阶段:用Vite或Vue CLI的代理,让本地服务转发请求,绕开浏览器拦截。
- 生产阶段:要么让后端配CORS响应头,要么用Nginx等做反向代理,让前端和后端“看起来同源”。
带Cookie、预检请求这些细节得盯紧,不然容易配了半天还报错,把这些逻辑理清楚,Vue3项目里的跨域问题就再也难不住你啦~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。