什么是跨域问题
在开发网页应用时,经常会遇到前端页面请求后端接口失败的情况,浏览器控制台报错提示‘CORS’或‘No 'Access-Control-Allow-Origin'’。这就是典型的跨域问题。简单来说,当一个网页尝试从不同域名、端口或协议去请求另一个资源时,浏览器出于安全考虑会阻止这个请求,除非服务器明确允许。
比如你在本地开发一个 Vue 项目,运行在 http://localhost:8080,而接口地址是 http://api.example.com,虽然只是域名不同,但已经构成跨域,浏览器就会拦截。
CORS:跨域资源共享机制
现代浏览器支持一种叫 CORS(Cross-Origin Resource Sharing)的机制,它通过 HTTP 头信息告诉浏览器,该请求是否被允许。服务器只要在响应头中加上 Access-Control-Allow-Origin,就能指定哪些源可以访问资源。
例如,后端返回以下响应头:
Access-Control-Allow-Origin: http://localhost:8080
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type, Authorization这样来自 http://localhost:8080 的请求就不会被拦截。如果想让所有来源都能访问,可以把值设为 *,但在涉及凭证(如 Cookie)时不能使用通配符。
实际开发中的处理方式
在前后端分离的项目中,前端通常由开发服务器启动,而后端运行在另一个端口上。这时候最常见的做法是在后端服务中配置 CORS 中间件。以 Node.js + Express 为例:
const cors = require('cors');
app.use(cors({
origin: 'http://localhost:8080',
credentials: true
}));Python 的 Flask 框架也可以用 flask-cors 扩展轻松实现:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app, origins='http://localhost:8080', supports_credentials=True)代理解决本地开发跨域
如果你无法修改后端配置,比如对接的是第三方接口,可以在前端开发服务器上设置代理。Vue CLI 和 Vite 都支持 proxy 配置。例如 Vite 的 vite.config.js:
export default {
server: {
proxy: {
'/api': {
target: 'http://api.example.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
}这样所有发往 /api 的请求都会被转发到目标地址,而浏览器认为请求还是发给同源,从而绕过跨域限制。
JSONP 曾经的跨域方案
在 CORS 出现之前,JSONP 是常用的跨域手段。它利用 <script> 标签不受同源策略限制的特性,动态加载一段 JavaScript 脚本,服务器返回函数调用的形式传递数据。不过 JSONP 只支持 GET 请求,安全性也较差,现在基本被 CORS 取代。
注意携带凭证时的细节
如果请求需要带上 Cookie 或认证头,必须在前端设置 withCredentials:
fetch('/api/data', {
credentials: 'include'
})同时服务器的 Access-Control-Allow-Origin 不能是 *,必须明确指定源,并且要开启 Access-Control-Allow-Credentials: true,否则浏览器依然会拒绝响应。
跨域不是 bug,而是浏览器的安全机制。理解它的规则,合理配置服务端和客户端,就能顺畅地完成接口调用。遇到问题时先看控制台报错,再检查请求头和响应头,大多数情况都能快速定位。”}