大白话跨域问题怎么破,解决方法有啥?
大白话跨域问题怎么破,解决方法有啥?
啥是跨域问题
咱先说说啥是跨域。你可以把每个网站想象成一个独立的小房子,每个房子都有自己的地址(也就是域名)。正常情况下,一个房子里的东西只能在这个房子里用,不能随便跑到别的房子里去。在网页开发里,浏览器有个“同源策略”,就像规定了房子和房子之间不能随便串门。如果一个网页要从它所在的域名去访问另一个域名下的资源,这就相当于要从一个房子跑到另一个房子去拿东西,浏览器就会阻止这种行为,这就是跨域问题。比如说,你在 http://www.example1.com
这个网站的页面里,想访问 http://www.example2.com
网站的接口数据,就会遇到跨域问题。
解决方法
1. JSONP(JSON with Padding)
- 原理:JSONP 利用了
<script>
标签的 src 属性不受同源策略限制的特点。就好比<script>
标签有个特殊通行证,可以去别的房子拿东西。服务器返回的数据会被包裹在一个回调函数里,网页通过<script>
标签请求这个带有回调函数的脚本,拿到数据后就可以在回调函数里处理。 - 代码示例
- 服务器端(Node.js + Express)
const express = require('express');
const app = express();
app.get('/data', (req, res) => {
const callback = req.query.callback;
const data = { message: '这是从服务器返回的数据' };
const jsonp = `${callback}(${JSON.stringify(data)})`;
res.send(jsonp);
});
const port = 3000;
app.listen(port, () => {
console.log(`服务器运行在端口 ${port}`);
});
- **客户端(HTML + JavaScript)**
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF - 8">
</head>
<body>
<script>
function handleData(data) {
console.log(data.message);
}
const script = document.createElement('script');
script.src = 'http://localhost:3000/data?callback=handleData';
document.body.appendChild(script);
</script>
</body>
</html>
- 优缺点
- 优点:兼容性好,几乎所有浏览器都支持。
- 缺点:只支持 GET 请求,安全性较低,容易受到 XSS 攻击。
2. CORS(Cross - Origin Resource Sharing,跨域资源共享)
- 原理:CORS 是一种现代的跨域解决方案,它是服务器端的一种机制。服务器通过设置响应头,告诉浏览器哪些域名可以访问它的资源,浏览器看到这些响应头后,就会允许跨域请求。就好比房子的主人给某些房子发了邀请函,拿到邀请函的房子里的人就可以来串门了。
- 代码示例
- 服务器端(Node.js + Express)
const express = require('express');
const app = express();
// 设置 CORS 响应头
app.use((req, res, next) => {
res.setHeader('Access - Control - Allow - Origin', '*'); // 允许所有域名访问
res.setHeader('Access - Control - Allow - Methods', 'GET, POST, PUT, DELETE');
res.setHeader('Access - Control - Allow - Headers', 'Content - Type');
next();
});
app.get('/data', (req, res) => {
const data = { message: '这是从服务器返回的数据' };
res.json(data);
});
const port = 3000;
app.listen(port, () => {
console.log(`服务器运行在端口 ${port}`);
});
客户端(HTML + JavaScript)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF - 8">
</head>
<body>
<script>
fetch('http://localhost:3000/data')
.then(response => response.json())
.then(data => console.log(data.message));
</script>
</body>
</html>
- 优缺点
- 优点:支持各种 HTTP 请求方法(GET、POST 等),安全性高。
- 缺点:需要服务器端进行配置,对于一些老旧服务器可能不支持。
3. 代理服务器
- 原理:代理服务器就像一个中间人。客户端把请求发给代理服务器,代理服务器再把请求转发给目标服务器,拿到目标服务器的响应后,再把响应返回给客户端。因为代理服务器和客户端在同一个域名下,所以不存在跨域问题。就好比你想从另一个房子拿东西,你把请求告诉一个住在你家附近的朋友,这个朋友去帮你从那个房子里把东西拿回来给你。
- 代码示例(开发环境下使用 Webpack 代理)
- Webpack 配置文件
const path = require('path');
const webpack = require('webpack');
const { WebpackDevServer } = require('webpack - dev - server');
const config = {
// 其他配置...
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000', // 目标服务器地址
changeOrigin: true,
pathRewrite: { '^/api': '' }
}
}
}
};
const compiler = webpack(config);
const server = new WebpackDevServer(compiler, config.devServer);
server.listen(8080, 'localhost', () => {
console.log('开发服务器运行在端口 8080');
});
- **客户端(HTML + JavaScript)**
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF - 8">
</head>
<body>
<script>
fetch('/api/data')
.then(response => response.json())
.then(data => console.log(data.message));
</script>
</body>
</html>
- 优缺点
- 优点:不需要服务器端进行额外配置,适合开发环境。
- 缺点:需要搭建代理服务器,增加了系统复杂度。
啥是跨域问题
咱先把跨域问题说明白。你可以把每个网站想象成不同的小区,每个小区都有自己的门禁系统(也就是浏览器的同源策略)。同源策略规定,只有同一个小区(也就是域名、端口、协议都相同)里的住户(页面资源)才能自由交流。要是一个小区的住户想和另一个小区的住户通信,就会被门禁拦住,这就是跨域问题。在前端开发里,当你用 React 或者 Vue 3 写的页面想去请求另一个域名下的接口数据时,就会遇到这种情况。
React 框架跨域问题及解决办法
开发环境下用代理服务器解决
- 原理:在开发的时候,就好比你请了一个跑腿小哥。你把请求交给这个小哥,小哥拿着你的请求去另一个小区(目标服务器)帮你办事,然后把结果带回来给你。因为小哥是你们小区(本地开发服务器)的人,所以能顺利进出,这样就绕过了门禁(同源策略)。
- 操作步骤
- 如果你用
create - react - app
创建的项目,在package.json
文件里加一行配置。比如目标服务器地址是http://api.example.com
,就在package.json
里加上"proxy": "http://api.example.com"
。这就相当于告诉跑腿小哥他要去的地方。 - 在 React 代码里发请求。比如你要请求
http://api.example.com/api/data
这个接口,代码里就写fetch('/api/data')
。因为有了前面的配置,开发服务器会自动把这个请求转发到目标服务器。
- 如果你用
import React, { useEffect } from'react';
function App() {
useEffect(() => {
async function getData() {
try {
const response = await fetch('/api/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('请求出错啦:', error);
}
}
getData();
}, []);
return (
<div>
<h1>React 跨域请求示例</h1>
</div>
);
}
export default App;
生产环境用 CORS 解决
- 原理:到了正式上线的生产环境,就不能用跑腿小哥了。这时候得让另一个小区(目标服务器)的门卫(服务器)给你发个通行证。服务器通过设置一些特殊的响应头,告诉浏览器你的小区(域名)可以访问它的资源。
- 操作步骤
- 服务器端设置。假设目标服务器用 Node.js 和 Express 搭建,在代码里加上下面这些设置:
const express = require('express');
const app = express();
// 设置允许访问的域名
app.use((req, res, next) => {
res.setHeader('Access - Control - Allow - Origin', 'http://your - react - app.com');
res.setHeader('Access - Control - Allow - Methods', 'GET, POST, PUT, DELETE');
res.setHeader('Access - Control - Allow - Headers', 'Content - Type');
next();
});
app.get('/api/data', (req, res) => {
const data = { message: '这是服务器返回的数据' };
res.json(data);
});
const port = 3000;
app.listen(port, () => {
console.log('服务器在端口 3000 运行');
});
- 在 React 代码里正常发请求就行。
import React, { useEffect } from'react';
function App() {
useEffect(() => {
async function getData() {
try {
const response = await fetch('http://api.example.com/api/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('请求出错啦:', error);
}
}
getData();
}, []);
return (
<div>
<h1>React 跨域请求示例</h1>
</div>
);
}
export default App;
Vue 3 框架跨域问题及解决办法
开发环境用代理服务器解决
- 原理:和 React 开发环境一样,也是请个跑腿小哥。Vue 3 一般用 Vue CLI 来开发,Vue CLI 的开发服务器能充当这个跑腿小哥。
- 操作步骤
- 在
vue.config.js
文件里配置代理。比如目标服务器是http://api.example.com
,文件内容可以这样写:
- 在
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://api.example.com',
changeOrigin: true,
pathRewrite: { '^/api': '' }
}
}
}
};
这里的 `/api` 是你本地请求的前缀,`target` 是目标服务器地址,`changeOrigin` 表示是否改变请求的源,`pathRewrite` 是对请求路径进行重写。
- 在 Vue 3 组件里发请求。
<template>
<div>
<h1>Vue 3 跨域请求示例</h1>
</div>
</template>
<script setup>
import { onMounted } from 'vue';
onMounted(async () => {
try {
const response = await fetch('/api/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('请求出错啦:', error);
}
});
</script>
生产环境用 CORS 解决
- 原理:同样是让目标服务器的门卫发通行证。
- 操作步骤
- 服务器端设置和前面 React 生产环境的服务器设置一样。
- 在 Vue 3 组件里正常发请求。
<template>
<div>
<h1>Vue 3 跨域请求示例</h1>
</div>
</template>
<script setup>
import { onMounted } from 'vue';
onMounted(async () => {
try {
const response = await fetch('http://api.example.com/api/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('请求出错啦:', error);
}
});
</script>