第13节:jQuery JSONP 与跨域请求(JSONP 原理、跨域请求实现、CORS 概念)
📘 引言
在现代 Web 开发中,跨域请求是一个常见且重要的问题。由于浏览器的同源策略限制,前端页面无法直接访问不同域的资源。本节课老曹将深入讲解跨域请求的解决方案,特别是 JSONP 的原理和使用,以及现代的 CORS 跨域资源共享机制。通过学习这些内容,你将能够处理各种跨域场景,实现更灵活的数据交互。
✅ 课程目标
目标项 | 内容 |
---|---|
知识目标 | 理解跨域问题的原理、掌握 JSONP 工作机制、了解 CORS 基本概念 |
能力目标 | 能够使用 jQuery 实现跨域请求、处理跨域数据交互 |
情感目标 | 认识跨域问题在实际开发中的重要性,培养解决复杂问题的能力 |
📌 一、跨域问题概述
✅1. 什么是同源策略?
同源策略是浏览器的安全机制,要求请求的 URL 必须与当前页面具有相同的:
- 协议(http/https)
- 域名(example.com)
- 端口(80/443/8080)
✅2. 什么是跨域?
当请求的 URL 与当前页面不满足同源条件时,就产生了跨域请求。
// 当前页面: http://localhost:3000/index.html
// 以下都是跨域请求:
http://api.example.com/data // 不同域名
http://localhost:8080/data // 不同端口
https://localhost:3000/data // 不同协议
http://www.localhost:3000/data // 不同子域名
✅3. 跨域的限制
浏览器会阻止以下跨域操作:
- Ajax 请求
- Cookie 读取
- localStorage/sessionStorage 访问
- iframe 内容访问
🧩 二、JSONP 原理与实现
✅1. JSONP 的工作原理
JSONP(JSON with Padding)利用了 <script>
标签不受同源策略限制的特性,通过动态创建 script 标签来实现跨域请求。
// JSONP 请求示例
function jsonp(url, callback) {
// 创建 script 标签
let script = document.createElement('script');
// 生成回调函数名
let callbackName = 'jsonp_callback_' + Math.round(100000 * Math.random());
// 将回调函数挂载到 window 对象上
window[callbackName] = function(data) {
callback(data);
// 清理工作
document.head.removeChild(script);
delete window[callbackName];
};
// 设置 script 的 src 属性
script.src = url + (url.indexOf('?') >= 0 ? '&' : '?') + 'callback=' + callbackName;
// 添加到页面中
document.head.appendChild(script);
}
✅2. jQuery 中的 JSONP 实现
// 使用 $.ajax() 实现 JSONP
$.ajax({
url: 'http://api.example.com/data',
dataType: 'jsonp',
jsonpCallback: 'myCallback',
success: function(data) {
console.log('获取数据:', data);
},
error: function() {
console.log('请求失败');
}
});
// 使用 $.getJSON() 实现 JSONP
$.getJSON('http://api.example.com/data?callback=?', function(data) {
console.log('获取数据:', data);
});
✅3. JSONP 的限制
- 只支持 GET 请求
- 安全风险(执行远程脚本)
- 错误处理困难
- 无法使用 XMLHttpRequest 的特性(如超时、取消等)
🌐 三、CORS 跨域资源共享
✅1. 什么是 CORS?
CORS(Cross-Origin Resource Sharing)是 W3C 标准,允许浏览器向跨域服务器发送 XMLHttpRequest 请求。它通过在 HTTP 头部增加额外字段来实现跨域访问控制。
✅2. 简单请求与复杂请求
简单请求条件:
- 请求方法:GET、POST、HEAD
- Content-Type:text/plain、multipart/form-data、application/x-www-form-urlencoded
- 无自定义头部
// 简单 CORS 请求
$.ajax({
url: 'http://api.example.com/users',
type: 'GET',
success: function(data) {
console.log(data);
}
});
复杂请求:
- 使用 PUT、DELETE 等方法
- Content-Type 为 application/json
- 包含自定义头部
// 复杂 CORS 请求(会先发送 OPTIONS 预检请求)
$.ajax({
url: 'http://api.example.com/users',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({ name: '张三' }),
success: function(data) {
console.log(data);
}
});
✅3. 服务端 CORS 配置示例
// Node.js Express 示例
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
next();
});
🎯 四、实际应用示例
✅1. 使用 JSONP 获取天气数据
// 调用天气 API(假设支持 JSONP)
$.ajax({
url: 'http://api.weather.com/current',
dataType: 'jsonp',
data: {
city: '北京',
key: 'your-api-key'
},
success: function(data) {
$('#weather').html(`
<h3>${data.city}天气</h3>
<p>温度: ${data.temperature}°C</p>
<p>湿度: ${data.humidity}%</p>
`);
},
error: function() {
$('#weather').html('<p>获取天气信息失败</p>');
}
});
✅2. 使用 CORS 获取用户数据
// 调用用户 API(支持 CORS)
$.ajax({
url: 'http://api.example.com/users',
type: 'GET',
xhrFields: {
withCredentials: true // 发送凭据(cookies)
},
success: function(users) {
let userList = '<ul>';
$.each(users, function(index, user) {
userList += `<li>${user.name} - ${user.email}</li>`;
});
userList += '</ul>';
$('#users').html(userList);
},
error: function(xhr) {
$('#users').html(`<p>获取用户列表失败: ${xhr.status}</p>`);
}
});
✅3. 跨域表单提交
$('#cross-domain-form').submit(function(e) {
e.preventDefault();
$.ajax({
url: 'http://api.example.com/submit',
type: 'POST',
dataType: 'json',
data: $(this).serialize(),
success: function(response) {
$('#result').html('<p>提交成功!</p>');
},
error: function(xhr) {
$('#result').html(`<p>提交失败: ${xhr.status}</p>`);
}
});
});
🧠 五、重难点分析
✅ 重点
- 理解 JSONP 的工作原理和使用场景
- 掌握 CORS 的基本概念和配置方法
- 能够根据需求选择合适的跨域解决方案
❗ 难点
- JSONP 与 CORS 的区别和适用场景
- 复杂请求的预检机制理解
- 服务端 CORS 配置的正确性
- 安全性考虑(如 withCredentials 的使用)
🧾 六、总结
本节课详细讲解了 jQuery 中处理跨域请求的相关知识,包括:
- 跨域问题的本质:浏览器同源策略的限制
- JSONP 原理:利用 script 标签实现跨域数据获取
- CORS 机制:现代跨域解决方案
- 实际应用:在项目中正确处理跨域请求
掌握这些内容后,你将能够应对各种跨域场景,实现更加灵活的数据交互功能。
在下一节中,我们将学习 jQuery 插件介绍与使用,了解常用插件的功能和使用方法,进一步提升开发效率。
📝 课后练习
- 使用 JSONP 调用一个公开的 API(如天气接口),并将结果显示在页面上。
- 配置一个支持 CORS 的简单服务器,并从前端发送跨域请求。
- 实现一个跨域搜索功能,用户输入关键词后从远程 API 获取搜索结果。
- 比较 JSONP 和 CORS 的优缺点,在不同场景下选择合适的方案。
- 创建一个跨域登录功能,处理认证凭据的跨域传递。
📚 推荐阅读
老曹建议在练习中重点关注安全性问题,合理配置跨域策略,避免造成安全漏洞。