概览
jQuery Ajax 跨域请求是指使用 jQuery 库中的 Ajax 功能向不同域名、协议或端口的服务器发起 HTTP 请求。由于浏览器的同源策略限制,默认情况下,脚本只能访问与当前页面相同来源的资源。jQuery 提供了两种主要机制来实现跨域请求:通过 JSONP 方式,以及利用现代浏览器支持的 CORS 标准。jQuery 的 $.ajax() 方法提供了相应的配置选项来处理跨域请求的不同场景,使得跨域数据交互的实现变得更加简洁。
同源策略与跨域
同源策略是浏览器的一种安全机制,它限制从一个源加载的文档或脚本与来自另一个源的资源进行交互。协议、域名和端口三者必须完全相同,才被视为同源。当 Ajax 请求的目标地址与当前页面地址不满足同源条件时,即构成 jQuery Ajax 跨域请求。浏览器会阻止这类请求直接获取数据,除非服务器端明确允许。jQuery Ajax 跨域请求正是为了在遵守安全策略的前提下,安全地打破这种限制。
JSONP
JSONP 是一种非官方的跨域数据交互协议。它利用 <script> 标签没有跨域限制这一特性,通过动态创建 <script> 标签,将其 src 属性指向支持跨域的服务端接口,并在 URL 中传递一个回调函数名。服务端返回的是一段 JavaScript 代码,该代码会调用这个回调函数,并将需要的数据作为参数传入。
$.ajax() 使用 JSONP
语法
$.ajax({
url: '跨域请求的地址',
dataType: 'jsonp',
jsonp: 'callback',
jsonpCallback: 'handleResponse',
success: function(data) {
// 处理返回的数据
}
});dataType: 'jsonp':指定请求类型为 JSONP,jQuery 会自动处理回调函数的生成与调用。jsonp:指定服务端接收回调函数名的参数名,默认为callback。jsonpCallback:指定回调函数名。若不指定,jQuery 会自动生成一个随机名称。
示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jQuery JSONP 跨域请求示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="fetchData">获取 GitHub 用户信息</button>
<div id="result"></div>
<script>
$('#fetchData').on('click', function() {
$.ajax({
url: 'https://api.github.com/users/jquery',
dataType: 'jsonp',
jsonpCallback: 'gitHubCallback',
success: function(data) {
$('#result').html('用户名: ' + data.data.login);
},
error: function() {
$('#result').html('请求失败');
}
});
});
</script>
</body>
</html>CORS
CORS 是一个 W3C 标准,它允许浏览器向跨源服务器发出 XMLHttpRequest 请求,从而克服了 Ajax 只能同源使用的限制。实现 CORS 主要依赖于服务器端的配置,需要在 HTTP 响应头中添加 Access-Control-Allow-Origin 等字段,声明允许访问的来源。对于简单的 GET 或 POST 请求,浏览器会自动在请求头中添加 Origin 字段,服务器根据此字段决定是否允许。
$.ajax() 使用 CORS
语法
$.ajax({
url: '支持 CORS 的跨域地址',
method: 'GET',
xhrFields: {
withCredentials: true // 如果需要发送 Cookie 等凭据
},
success: function(data) {
// 处理返回的数据
}
});xhrFields.withCredentials:布尔值,表示跨域请求是否应携带凭据(如 Cookie、HTTP 认证信息)。设置为true时,服务器端的Access-Control-Allow-Origin不能为*,必须指定具体的域名,且需设置Access-Control-Allow-Credentials: true。
示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jQuery CORS 跨域请求示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="fetchData">请求公开 API 数据</button>
<div id="result"></div>
<script>
$('#fetchData').on('click', function() {
$.ajax({
url: 'https://api.github.com/users/jquery',
method: 'GET',
dataType: 'json',
success: function(data) {
$('#result').html('仓库数量: ' + data.public_repos);
},
error: function(xhr, status, error) {
$('#result').html('请求失败: ' + error);
}
});
});
</script>
</body>
</html>$.ajax() 跨域相关选项
$.ajax() 方法提供了多个与 jQuery Ajax 跨域请求相关的配置选项,用于精细控制请求行为。
crossDomain
语法
$.ajax({
crossDomain: true,
// 其他选项
});crossDomain:布尔值,默认为同域请求时为false,跨域请求时为true。强制设置此选项为true可避免同域重定向到跨域时可能出现的内部优化问题。对于 JSONP 请求,该值会自动设置为true。
jsonp 与 jsonpCallback
语法
$.ajax({
dataType: 'jsonp',
jsonp: 'cb',
jsonpCallback: 'myCallback'
});jsonp:重写回调函数名的查询参数名,默认为callback。例如,设置jsonp: 'cb'后,请求 URL 将包含cb=?。jsonpCallback:指定固定的回调函数名。若省略,jQuery 会生成一个随机唯一名称,这有助于避免缓存。指定固定名称可能便于调试,但需注意函数名的全局唯一性,否则可能导致冲突。
xhrFields
语法
$.ajax({
xhrFields: {
withCredentials: true
}
});xhrFields:一个对象,用于设置原生的XMLHttpRequest对象上的属性。在跨域请求中,最常用的属性是withCredentials,用于指示是否发送凭据。
示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>跨域请求选项综合示例</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
</head>
<body>
<button id="corsRequest">发送 CORS 请求</button>
<button id="jsonpRequest">发送 JSONP 请求</button>
<div id="output"></div>
<script>
$('#corsRequest').on('click', function() {
$.ajax({
url: 'https://api.github.com/users/jquery',
crossDomain: true,
xhrFields: { withCredentials: false },
success: function(data) {
$('#output').html('CORS 成功: ' + data.name);
},
error: function() {
$('#output').html('CORS 请求失败');
}
});
});
$('#jsonpRequest').on('click', function() {
$.ajax({
url: 'https://api.github.com/users/jquery',
dataType: 'jsonp',
jsonp: 'callback',
success: function(data) {
$('#output').html('JSONP 成功: ' + data.data.name);
}
});
});
</script>
</body>
</html>跨域请求的浏览器支持与限制
jQuery Ajax 跨域请求的实现依赖于浏览器的底层支持。JSONP 的支持非常广泛,几乎所有浏览器都支持。CORS 则在现代浏览器中得到良好支持。
| 特性 | 描述 | 限制 |
|---|---|---|
| JSONP | 利用 <script> 标签的跨域能力,只支持 GET 请求。通过动态创建 <script> 并插入 DOM 来实现。 | 仅支持 GET 方法,无法处理错误状态码(如 404),安全性较低(可能执行恶意代码),受限于所请求服务器必须支持 JSONP 输出。 |
| CORS | 基于 HTTP 头的标准协议,支持 GET、POST、PUT、DELETE 等所有 HTTP 方法。浏览器自动处理预检请求(OPTIONS)。 | 需要服务器端配置相应的响应头(如 Access-Control-Allow-Origin)。旧版浏览器(如 IE10 以下)支持不完善。需要处理预检请求以优化性能。 |
版本变更记录
| 版本 | 变更说明 |
|---|---|
| 1.2 | 引入了对 JSONP 的支持,在 $.ajax() 中增加了 dataType: 'jsonp' 选项。 |
| 1.5 | 重构了 Ajax 模块,引入了 jqXHR 对象,增强了对包括跨域请求在内的异步操作的控制能力。对 CORS 的支持更加完善,能够更好地与原生 XMLHttpRequest Level 2 的特性集成。 |
| 3.0 | 进一步优化了对 Promise 的兼容性,使得跨域请求的链式调用更符合标准。明确了对 CORS 中 withCredentials 选项的支持。 |
| 4.0 | 移除了对 IE 10 及更早版本的支持,这些版本对 CORS 的支持存在缺陷。对于跨域脚本请求,优先使用 <script> 标签而非 XHR,以更好地符合 CSP 规则,避免因内联脚本导致的 CSP 错误。 |
浏览器兼容性
jQuery 3.x 及 4.x 版本对浏览器兼容性的要求有所不同,这直接影响到 jQuery Ajax 跨域请求的可用性。以下基于 jQuery 4.x 版本(移除了对 IE<11 的支持)的兼容情况。
| 浏览器类型 | 最低兼容版本 | 跨域支持说明 |
|---|---|---|
| PC 端 | ||
| Chrome | 60+ (当前及先前主要版本) | 完全支持 CORS 和 JSONP。 |
| Edge | 15+ (基于 Chromium) | 完全支持 CORS 和 JSONP。 |
| Firefox | 55+ (当前及先前主要版本) | 完全支持 CORS 和 JSONP。 |
| Opera | 47+ (当前及先前主要版本) | 完全支持 CORS 和 JSONP。 |
| Safari | 10+ (当前及先前主要版本) | 完全支持 CORS 和 JSONP。 |
| 移动端 | ||
| Chrome Android | 100+ (当前版本) | 完全支持 CORS 和 JSONP。 |
| Firefox for Android | 100+ (当前版本) | 完全支持 CORS 和 JSONP。 |
| Opera Android | 64+ (当前版本) | 完全支持 CORS 和 JSONP。 |
| Safari on iOS | 10+ | 完全支持 CORS 和 JSONP。 |
| Samsung Internet | 6.2+ | 完全支持 CORS 和 JSONP。 |
| WebView Android | 100+ (当前版本) | 支持 CORS 和 JSONP,行为与 Chrome 一致。 |
| WebView on iOS | 10+ | 支持 CORS 和 JSONP,行为与 Safari on iOS 一致。 |
通过理解同源策略的限制,并掌握 JSONP 与 CORS 这两种跨域解决方案及其在 jQuery 中的具体实现,可以有效地利用 jQuery Ajax 跨域请求来构建能够与外部服务交互的 Web 应用。选择何种方式取决于目标服务器提供的支持以及应用场景的具体需求。
