本文解析浏览器同源策略导致的跨域问题,介绍CORS、代理、PostMessage等常见解决方案。重点讲解JSONP原理,通过动态创建script标签实现GET跨域请求,并提供了完整的客户端与服务端JSONP手写代码示例及注意事项。
跨域问题与常见解决方案
跨域源于浏览器的同源安全策略,该策略规定只有当协议、域名和端口号完全一致时,网页间才能共享资源。若上述条件任一不匹配,即被视为跨域。
针对跨域问题,业界存在多种解决思路:
1. CORS(跨源资源共享):服务器通过配置 Access-Control-Allow-Origin 响应头来允许特定来源访问,这是目前最主流的跨域处理方式。
// 服务器端设置 HTTP 头部
res.setHeader('Access-Control-Allow-Origin', '*');
2. JSONP(JSON with Padding):利用动态生成 <script> 标签的特性,调用服务器提供的回调函数。此方式仅支持 GET 请求。
// 客户端
function handleResponse(data) {
console.log(data);
}
const script = document.createElement('script');
script.src = 'http://www.domain.com?callback=handleResponse';
document.body.insertBefore(script, document.body.firstChild);
// 服务器端
res.end(`handleResponse(${JSON.stringify(data)})`);
3. 代理服务器:由后端服务器代为转发请求与响应,从而规避浏览器直接访问不同源资源的安全限制。
// Node.js 服务器端
const request = require('request');
app.get('/proxy', function(req, res) {
const url = 'http://www.domain.com' + req.url;
req.pipe(request(url)).pipe(res);
});
4. PostMessage:HTML5 规范引入的 API,支持不同源窗口间的跨域通信。
// 页面 A
window.postMessage('message', 'http://www.domain-b.com');
// 页面 B
window.addEventListener('message', function(event) {
if (event.origin !== 'http://www.domain-a.com') return;
console.log(event.data);
}, false);
5. WebSockets:作为一种双向通信协议,WebSockets 在建立连接后可直接传输数据,因此不受同源策略约束。
上述为常见的跨域解决手段,实际应用中需根据具体场景与需求进行选型。
JSONP 原理与手写实现
JSONP(JSON with Padding)是一种基于 script 标签的跨域数据交互方案。其核心逻辑是网页插入 <script> 标签向服务器请求 JSON 数据,该方式不受同源策略限制;服务器接收请求后,将数据封装在指定名称的 JavaScript 函数中返回。
以下展示 JSONP 的基础实现逻辑:
// 客户端
function jsonp(url, callback) {
// 创建 script 标签并加入到页面中
var script = document.createElement('script');
script.type = 'text/javascript';
// 创建一个全局函数,并将函数名传给服务器请求
var callbackName = 'jsonp_callback_' + Math.random().toString().replace('.', '');
window[callbackName] = function(data) {
// 在这个全局函数中处理服务器返回的数据
callback(data);
// 数据处理完后删除此函数及 script 标签
delete window[callbackName];
document.body.removeChild(script);
}
// 设置请求 URL
script.src = url + '?callback=' + callbackName;
document.body.appendChild(script);
}
// 使用 JSONP
jsonp('http://www.example.com', function(data) {
console.log(data);
});
在此示例中,客户端预先定义一个全局函数,并将函数名作为参数传递给服务器。服务器将数据包裹在该函数名中返回,客户端的全局函数接收数据后执行相应处理。
需注意,JSONP 仅支持 GET 请求,无法发送 POST 等其他 HTTP 方法。此外,由于依赖插入 <script> 标签机制,若服务器被恶意利用,可能引发安全风险。
本文关于 JavaScript 跨域问题解析及 JSONP 手写实现的介绍至此结束,更多相关技术内容欢迎查阅本站往期文章或继续浏览后续章节,感谢支持!