如何跨域获取其他网站的JSON数据:从基础到实践的完整指南
在现代Web开发中,跨域获取JSON数据是一项高频需求——无论是集成第三方API(如天气、地图、支付服务)、爬取公开数据,还是实现前后端数据分离,都离不开从其他网站提取JSON格式数据,但由于浏览器的“同源策略”(Same-Origin Policy),直接跨域请求会被限制,本文将系统介绍合法合规的跨域获取JSON数据的方法,从基础原理到代码实践,助你这一核心技能。
理解核心限制:同源策略与跨域问题
什么是同源策略?
同源策略是浏览器的重要安全机制,它规定:如果页面的协议(protocol)、域名(domain)、端口(port)三者中任意一项与目标资源不同,则该页面被认定为“不同源”,浏览器会阻止其对目标资源的直接访问。
页面 https://www.example.com/index.html 请求以下资源时:
https://www.example.com/api/data✅ 同源(协议、域名、端口均相同)http://www.example.com/api/data❌ 不同源(协议不同)https://api.example.com/data❌ 不同源(域名不同)https://www.example.com:8080/api/data❌ 不同源(端口不同)
为什么跨域请求会被拦截?
同源策略的核心目的是防止恶意网站读取用户的敏感数据(如Cookie、Token),假设你已登录 https://your-bank.com,若没有同源策略,恶意网站 https://evil.com 可通过JavaScript向 your-bank.com 发起请求,窃取你的账户信息,浏览器默认会阻止跨域请求的响应数据(即使服务器允许)。
合法跨域获取JSON的5种主流方法
既然直接跨域被限制,我们需要借助“合法通道”实现数据获取,以下是5种主流方法,按使用场景和复杂度排序,从最推荐的CORS到特定场景的JSONP。
方法1:CORS(跨域资源共享)——现代Web的黄金标准
原理:
CORS(Cross-Origin Resource Sharing)是W3C标准,通过服务器在HTTP响应头中添加特定字段,明确允许哪些域名发起跨域请求,浏览器检测到服务器的“许可”后,会放行响应数据。
实现步骤:
服务器配置CORS响应头
服务器需在响应中添加以下关键头:
Access-Control-Allow-Origin: * # 允许所有域名访问(不安全,生产环境建议指定具体域名,如 https://your-website.com) Access-Control-Allow-Methods: GET, POST, PUT # 允许的请求方法 Access-Control-Allow-Headers: Content-Type, Authorization # 允许的请求头 Access-Control-Allow-Credentials: true # 是否允许携带Cookie(需配合前端credentials属性)
不同语言的配置示例:
-
Node.js (Express):
const express = require('express'); const app = express(); // 允许所有域名跨域(生产环境建议替换为具体域名) app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Methods', 'GET, POST, PUT'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization'); next(); }); // 示例API app.get('/api/data', (req, res) => { res.json({ message: '这是CORS允许的JSON数据' }); }); app.listen(3000); -
Nginx:
location /api/ { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST'; add_header 'Access-Control-Allow-Headers' 'Content-Type'; }
前端发起请求(无需特殊处理,浏览器自动检测CORS头)
使用 fetch 或 axios 即可,无需额外配置:
// 使用fetch(推荐现代浏览器)
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) throw new Error('请求失败');
return response.json(); // 解析JSON数据
})
.then(data => console.log(data))
.catch(error => console.error('错误:', error));
// 使用axios(需安装:npm install axios)
axios.get('https://api.example.com/data')
.then(response => console.log(response.data))
.catch(error => console.error('错误:', error));
注意事项:
- 若请求需要携带Cookie(如用户登录状态),需设置:
fetch('https://api.example.com/data', { credentials: 'include' // 发送Cookie(需服务器配置Access-Control-Allow-Credentials: true) }); Access-Control-Allow-Origin: *与credentials: 'include'不能同时使用(否则会报错),需指定具体域名。
方法2:JSONP(仅支持GET请求的“古早方案”)
原理:
JSONP(JSON with Padding)利用了<script>标签的跨域能力(浏览器允许加载外部JS资源),通过动态创建<script>标签,请求URL中带一个回调函数名,服务器返回该函数包裹的JSON数据,前端通过回调函数处理数据。
实现步骤:
前端定义回调函数
function handleResponse(data) {
console.log('获取的JSON数据:', data);
}
动态创建<script>标签发起请求
const script = document.createElement('script');
script.src = 'https://api.example.com/data?callback=handleResponse'; // 回调函数名作为参数
document.body.appendChild(script);
// 请求完成后移除标签(可选)
script.onload = () => script.remove();
服务器返回JSONP格式数据
服务器需将JSON数据包裹在回调函数中返回:
// 服务器返回的响应内容(不是纯JSON,而是函数调用)
handleResponse({ message: '这是JSONP返回的数据', code: 200 });
注意事项:
- 仅支持GET请求:无法用于POST/PUT等请求。
- 安全性风险:回调函数名若被恶意利用(如XSS攻击),需确保回调函数来源可信。
- 逐渐淘汰:现代API基本不再支持JSONP,优先选择CORS。
方法3:代理服务器——绕过浏览器限制的“中间人”
原理:
如果目标服务器不支持CORS,或你无法修改其配置,可通过搭建代理服务器(如Nginx、Node.js)实现“同源转发”,前端请求同源的代理接口,代理服务器再转发请求到目标服务器,最后将结果返回给前端。
实现步骤:
搭建Node.js代理服务器(示例)
// server.js (使用http-proxy-middleware)
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
// 代理配置:将 /api 开头的请求转发到目标服务器
app.use('/api', createProxyMiddleware({
target: 'https://target-api.example.com', // 目标服务器地址
changeOrigin: true, // 修改请求头中的Origin为目标服务器地址
pathRewrite: { '^/api': '' } // 可选:重写路径(如 /api/data -> /data)
}));
app.listen(3000, () => {
console.log('代理服务器运行在 http://localhost:3000');
});
前端请求同源代理接口
// 前端请求本地代理接口(无跨域问题)
fetch('/api/data') // 实际请求 https://target-api.example.com/data
.then(response => response.json())
.then(data => console.log(data));
注意事项:
- 需要自己维护代理服务器(可部署在云服务器或Vercel/Netlify等平台)。
- 代理服务器会暴露目标API的URL,若涉及敏感数据,需在代理层添加鉴权逻辑。
方法4:服务端请求(完全绕过浏览器限制)
原理:
浏览器无法跨域,但服务端没有同源策略限制,可在后端代码(如Node.js、Python、Java)中发起HTTP请求获取目标JSON数据,再通过API返回给前端。
实现步骤:
后端获取目标JSON(Node.js示例)
const express = require('express');
const axios = require('axios'); // 需安装:npm install axios
const app = express();
app.get('/api/remote-data', async (req, res) => {
try {
const response = await axios.get('https://target-api.example.com/data'); //


还没有评论,来说两句吧...