老生常谈的跨域问题JSONP解决方式

原由

提及来源...今天去茶水间倒水时,偶然听到公司面试官在问面试者前端跨域的如何解决。我心中默默想了一想,啪啪啪瞬间想出几个关键词,iframe,cors,同源策略,jsonp...转念一想,虽然这是很常见的面试题,然而我在开发过程当中,还真没有用过jsonp这种方式...就连原理也说很差。一阵冷汗,? ,赶忙去找了相关资料。javascript

同源策略

对于同源策略,在这里我就很少累赘叙述了,简单来讲,若是如下三项:同一协议同一域名同一端口但凡是有一项不知足,浏览器就会把 No 'Access-Control-Allow-Origin' header is present on the requested resource甩你一脸。前端

解决方案

跨域问题能够说在前端方面不可避免,但同源策略毕竟在保护网络信息安全方面起到很大的做用。试想若是没有同源策略,别的网页能够轻松窃取你的cookie,而假如你的cookie中存有你的我的信息...太可怕了,不过话说回来同源策略带来的跨域问题也很头疼,幸亏如今已经有多种方式可以解决。java

  1. CORS 跨域资源共享策略(web

  2. JSONP面试

  3. window.nameajax

  4. document.domain(主域相同的状况下可用)json

  5. postMessage(h5新引入)跨域

  6. websocket(h5新引入,不受同源策略限制,因此说h5真是个好东西...?)浏览器

  7. ...安全

因为篇幅有限(好吧...实际上是我写不了那么多),在这里对于其余解决方式就不一一详解了。

正主来了,JSONP

JSONPJSON with Padding的简称,是一种较为经常使用的解决跨域访问的方式。咱们先来看一段示例代码:

ajax({//此ajax方法是封装了XMLHttpRequest对象实现,具体代码与本文无关就不贴了
  method : 'get',
  url : 'http://127.0.0.1:8787',
  data : {
  'name' : '小明',//此ajax方法会自动将数据以get方式提交
  'age' : 22
  },
  success : function (message) {
    alert(message);
  },
  async : true
})

上面的代码很简单,浏览器端发起了一个异步ajax请求,让咱们来看看服务端代码:

app.get('*', function(req, res) {//这里只截取了关键代码
  res.send("测试数据");
});

清晰,易懂~so,what happend?

跨域报错

不出所料,浏览器甩了我一脸...
易地再战!JSONP炸裂出场~

function showJsonp(obj){
  console.log(obj.message);
}
var url = 'http://127.0.0.1:8787/?func=showJsonp'
var script = document.createElement('script');
script.setAttribute('src',url);
script.setAttribute('type','text/javascript');
document.getElementsByTagName('head')[0].appendChild(script);

再来后台代码~

app.get('*', function(req, res) {
  let callback = req.query.func;
  let content = callback+"({'message':'测试数据2'})";
  res.send(content);
});

结果:

jsonp解决跨域

大!获!全!胜!
是时候分析一波战术策略了~在日常写代码的时候,可能不少人没有注意,浏览器对于script,iframe等标签的src等属性,是没有同源策略限制的。而jsonp就很好的利用了这一点~在咱们发起请求时,url后跟了一个名为func的参数,而这个参数就是以后须要用到的回调函数名称。
咱们经过动态插入script标签的方式,利用script标签的src属性发起请求,浏览器不会以同源策略来找事...然后台根据请求构造出的数据长啥样呢?

showJsonp({'message':'测试数据2'})

告诉我!这段代码插入你的script标签内后,会发生啥?!
固然是执行早就定义好的showJsonp函数啊~
bingo,完美解决跨域问题~~

最后

jsonp的方式兼容性很是好,即使是那些老古董浏览器,也能够用jsonp的方式解决跨域问题,可是它也有所限制,它只能使用get方式发起请求,而且对于不一样域之间页面的js互相调用无能为力。

相关文章
相关标签/搜索