您的位置:

深入剖析jsonp跨域

一、jsonp跨域是什么

1、由来

在Web应用中,为了保证用户浏览的速度,许多网页会采用Ajax技术在页面上进行部分刷新,在这个过程中,为了保护用户的信息和系统的安全,服务器放置了许多控制访问的机制,如同源策略(Same Origin Policy)。这个策略禁止一个网页去调用另一个来源的页面上的资源。例如,stogege.com的网页脚本无法取得www.google.com的内容,因为它们不是同源。

但有些情况下,我们需要在不同的域名或端口之间进行数据交互,这时候就需要使用jsonp跨域技术。

2、原理

JSONP(“JSON with padding”)是JSON的一种“使用模式”,可以让网页从别的域名(网站)那获取资料,即跨域读取数据。Jsonp的实现方法就是在服务器端加上一个回调函数,然后返回时将数据作为这个回调函数的参数,然后客户端通过 script 标签引入这个 URL,就可以拿到远程返回的 JS 代码,并在回调函数里面拿到拿到数据了。由于同源策略的限制,XmlHttpRequest无法跨越域名获取数据,而script标签的SRC属性是没有跨域限制的。这样适用JSONP实现跨域数据请求。

// client端
function addScriptTag(src) {
  var script = document.createElement('script');
  script.setAttribute("type","text/javascript");
  script.src = src;
  document.body.appendChild(script);
}
 
window.onload = function () {
  addScriptTag('http://domain2.com:8080/login?user=admin&callback=foo');
};
 
function foo(data) {
  alert('Your name is ' + data.name);
}
 
// server端
if (url.parse(req.url, true).pathname === '/login') {
  var data = {name: 'admin'};
  var callback = url.parse(req.url, true).query.callback;
  if (callback) {
    res.end(callback + '(' + JSON.stringify(data) + ')');   
  } else {
    res.end(JSON.stringify(data));
  }
}

二、jsonp的优缺点

1、优点

(1)兼容性好:JSONP在实现上比较简单,在老式浏览器上都可以兼容正常使用;

(2)能够使用不同源下的已存在的服务:JSONP通过script标签来调用,无须Ajax的标准化支持,因此可以跨越不同源而无需要后台支持;

2、缺点

(1)可读性差:JSONP返回的数据要求是JSON格式的,这种格式对于阅读来说不太友好,可读性差;

(2)不安全:JSONP是可以进行跨域操作的,也就意味着当被请求的服务存在安全漏洞时,这种操作可能会导致一定的安全风险,代码难以维护。

三、jsonp的应用场景

1、富客户端Web应用

富客户端Web应用通常需要动态获取各种数据,这些数据通常来自不同的域名,而JSONP正是一种跨域的手段,使得这些数据能够被成功地获取。

2、第三方数据解析

第三方的数据解析通常有两种方式:一个是通过后台进行转发,另外一个就是使用JSONP来实现,将解析到的数据直接返回到前端,使用JSONP进行数据解析。

四、jsonp的实现过程

1、前端请求

function jsonp(url, params, callback) {
  const script = document.createElement('script');
  const src = url + '?' + jsonpParams(params, callback);
  script.setAttribute('src', src);
  document.body.appendChild(script)
}
function jsonpParams(params, callback) {
  let str = '';
  const callbackName = 'jsonp_callback_' + parseInt(+new Date() / 1000);
  window[callbackName] = (data) => {
    try {
      callback && callback(data);
    } catch (e) {}
    delete window[callbackName];
    document.body.removeChild(script);
  };
  str = 'callback=' + callbackName;
  for (let key in params) {
    str += '&' + key + '=' + params[key];
  }
  return str;
}
jsonp('http:// domain2.com:8080/login', {user: 'admin'}, (data) => {
  console.log(data);
});

2、后端响应

if (/^\/api\/jsonp$/i.test(req.pathname)) {
  const data = JSON.stringify({id: 1, name: 'test'});
  res.end(`${req.query.callback}(${data})`);
}

五、jsonp的安全问题

使用JSONP跨域时,由于callback参数不是用户手动输入的,而是后台修改后返回给前端的,所以不会被攻击者通过输入脚本的方式进行攻击。但是如果不对服务端返回的数据进行过滤的话,就会存在XSS攻击的风险。使用JSONP跨域时,服务端应该仅返回经过校验的、安全的数据。

六、总结

jsonp跨域技术是在Web应用的开发中经常使用的一种技术手段。虽然它有许多限制和不足,但因其简单易懂,兼容性好,能够优雅地解决同源策略问题,而被广泛应用于Web应用的开发中。