什么是跨域?
跨域(Cross-Origin)是指浏览器的同源策略(Same-Origin Policy)阻止了不同源之间的资源访问。"同源"要求以下三个部分都相同:
-
协议(Protocol):如 http/https
-
域名(Domain):如 localhost、example.com
-
端口(Port):如 8080、3000
例如:
前端地址:http://localhost:8080
后端地址:http://127.0.0.1:8000
这种情况就属于跨域(端口不同)。
为什么会有跨域限制?
跨域限制是浏览器的一种安全机制,目的是防止恶意网站获取其他网站的敏感数据。这种限制只存在于浏览器端,服务器之间的通信是不受此限制的
开发环境中的跨域
1. 代理方式(前端配置)
通过在开发服务器配置代理来解决:
devServer: {
proxy: {
'/api': {
target: 'http://127.0.0.1:8000',
changeOrigin: true
}
}
}
工作原理:
浏览器 ---> 开发服务器(8080) ---> 后端服务器(8000)
优点:
-
不需要修改后端代码
-
只在开发环境中生效
-
配置简单
2. CORS(后端配置)
# Python/Django示例
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE'
response.headers['Access-Control-Allow-Headers'] = 'Content-Type'
3. JSONP(已过时)
只支持GET请求,现代开发中较少使用。
生产环境的解决方案
1.同源部署:
-
将前端资源部署到后端服务器
-
前后端使用相同的域名
2.配置CORS:
-
后端正确配置CORS响应头
-
允许特定域名访问
3.nginx反向代理:
location /api {
proxy_pass http://backend-server;
}
实际项目配置示例
1.开发环境配置(.env.development):
VUE_APP_API_URL=/api
VUE_APP_BASE_URL=http://127.0.0.1:8000
2.生产环境配置(.env.production):
VUE_APP_API_URL=/api
VUE_APP_BASE_URL=http://production-api.com
3.代理配置(vue.config.js):
devServer: {
proxy: {
'/api': {
target: process.env.VUE_APP_BASE_URL,
changeOrigin: true
}
}
}
常见问题
OPTIONS预检请求:
-
复杂请求会先发送OPTIONS请求
-
需要后端正确响应OPTIONS请求
Cookie跨域:
-
需要设置 withCredentials: true
-
后端设置 Access-Control-Allow-Credentials: true
-
Access-Control-Allow-Origin 不能为 *
代理失效:
-
检查代理配置是否正确
-
确认目标服务器是否可访问
-
查看开发服务器控制台错误信息
总结
-
跨域是浏览器的安全限制,不是后端的限制
-
开发环境推荐使用代理方式解决跨域
-
生产环境建议使用同源部署或正确配置CORS
-
选择合适的跨域解决方案要考虑
我自己项目上的实际配置
.env.development文件
VUE_APP_API_URL=/api
# 指向本地服务器地址
VUE_APP_BASE_URL=http://127.0.0.1:8000
# 指向远程服务器地址
# VUE_APP_BASE_URL=http://xxx
.vue.config.js文件
const { defineConfig } = require('@vue/cli-service')
const webpack = require('webpack')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: true,
devServer: {
proxy: {
'/api': {
target: process.env.VUE_APP_BASE_URL,
changeOrigin: true,
// pathRewrite: { // 如果后端接口没有使用 /api 前缀,则需要注释掉
// '^/api': ''
// }
},
'/storage': {
target: process.env.VUE_APP_BASE_URL,
changeOrigin: true
}
}
},
configureWebpack: {
plugins: [
new webpack.DefinePlugin({
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: JSON.stringify(false)
})
]
}
})