什么是跨域 ?
跨域是指在浏览器中,当前网页从不同域名、协议或端口请求资源时,出现的安全限制问题。通常,这种限制被称为同源策略,它是浏览器的一种安全机制,用于防止恶意网站读取另一个网站的数据。
同源策略
同源策略规定,只有当协议、域名和端口三者都相同的时候,才允许进行请求。
例如:
· 同源:
http://www.baidu.com与http://www.baidu.com:80
· 不同源:
http://www.baidu.com与https://www.baidu.com(协议不同)
常见的跨域场景
- AJAX 请求不同源的 API。
- 通过
<script>标签加载不同源的脚本文件(虽然这种方式不受同源策略限制,但存在其他安全问题)。 - 使用
iframe加载不同源的页面。 - WebSocket 连接不同源的服务。
跨域解决方法
1. JSONP
JSONP (JSON with Padding) 是一种通过动态添加 <script> 标签来跨域获取数据的方式。服务器返回的不是 JSON 格式的数据,而是一个 JavaScript 函数的调用。
客户端代码:
function handleResponse(response) {
console.log(response);
}
var script = document.createElement('script');
script.src = 'http://example.com/data?callback=handleResponse';
document.head.appendChild(script);
服务器响应:
handleResponse({"message": "Hello, world!"});
优点:
- 简单易用,支持所有浏览器。
- 不受同源策略限制。
缺点:
- 仅支持 GET 请求。
- 存在安全风险,容易被利用进行 XSS 攻击。
2. CORS
CORS (Cross-Origin Resource Sharing) 是一种允许服务器指示哪些来源站点可以访问资源的机制。服务器通过设置 HTTP 头来实现跨域访问。
服务器设置:
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type
客户端请求:
fetch('http://example.com/data', {
method: 'GET',
credentials: 'include'
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
优点:
- 安全性高,可以灵活控制允许的跨域请求。
- 支持多种 HTTP 方法。
缺点:
- 需要服务器配置支持。
- 对于复杂请求会进行预检(preflight)请求,增加了开销。
3. 代理服务器
通过在同源服务器上设置代理,转发请求到目标服务器,解决跨域问题。
客户端请求:
fetch('/api/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
代理服务器配置(例如使用 Node.js + Express):
const express = require('express');
const request = require('request');
const app = express();
app.use('/api', (req, res) => {
const url = 'http://example.com' + req.url;
req.pipe(request(url)).pipe(res);
});
app.listen(3000, () => {
console.log('Proxy server listening on port 3000');
});
优点:
- 对客户端透明,配置简单。
- 支持各种请求方法和头信息。
缺点:
- 增加了服务器负载。
- 需要维护代理服务器。
4. WebSocket
WebSocket 是一种全双工通信协议,可以用来在浏览器和服务器之间建立持久连接,允许跨域通信。
服务器端(Node.js):
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', ws => {
ws.on('message', message => {
console.log('received:', message);
});
ws.send('Hello from server');
});
客户端:
const socket = new WebSocket('ws://example.com:8080');
socket.onopen = function() {
socket.send('Hello from client');
};
socket.onmessage = function(event) {
console.log('Message from server:', event.data);
};
优点:
- 支持实时双向通信。
- 不受同源策略限制。
缺点:
- 需要服务器和客户端都支持 WebSocket 协议。
- 存在一定的学习和实现成本。
5. 使用 Vue CLI 的代理配置
Vue CLI 提供了开发服务器代理选项,可以轻松地将 API 请求代理到不同的服务器。这是最常见和最简单的方法。
步骤:
- 在 Vue 项目的根目录下,找到 vue.config.js 文件。如果没有这个文件,可以创建一个。
- 在 vue.config.js 中添加以下代码:
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://example.com', // 目标服务器的地址
changeOrigin: true, // 是否改变源
pathRewrite: { '^/api': '' }, // 将请求路径中的 /api 替换为空字符串
},
},
},
};
说明:
- '/api' 是你在前端代码中使用的路径前缀。
- target 是你要代理的目标服务器。
- changeOrigin 设置为 true,表示代理时修改请求头中的 Host 为目标地址。
- pathRewrite 是可选的,用于重写路径,比如将 /api 前缀去掉。
使用示例:
前端代码中调用 API 时:
axios.get('/api/data')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});
总结
跨域是前端开发中常见的问题,通过不同的技术和方法可以有效地解决。选择合适的解决方案需要考虑安全性、兼容性和具体业务需求。CORS 是目前最常用的方法,JSONP 适用于简单的 GET 请求,而代理服务器和 WebSocket 则可以用于更复杂的跨域通信需求。
955

被折叠的 条评论
为什么被折叠?



