经常使用跨域方法实践(一)

这几天看了鬼道师兄的《跨终端Web》这本书,该书从解决实际业务出发,讲述了跨终端的优点与将来,受益良多。其中,书中第九章介绍了做者在阿里内部的一个参赛做品Storage,该做品巧妙的使用了跨域知识,让我见识到跨域其实不单单是JSONP。之前,对前端跨域这块或多或少有点了解,但真正动手实践的不是不少。因而,这段时间我好好整理了经常使用跨域方法的具体实现。本文,主要介绍了JSONPCORS的实现方式。javascript

相关概念:html

  • 只要协议、域名、端口有任何一个不一样,都被看成是不一样的域
  • JavaScript出于安全方面的考虑,不容许跨域调用其余页面的对象
  • 跨域简单地理解就是由于JavaScript同源策略的限制,a.com域名下的js没法操做b.com或是c.a.com域名下的对象

注意:前端

  • 若是是协议和端口形成的跨域问题“前台”是无能为力的
  • 在跨域问题上,域仅仅是经过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上(“URL的首部”指window.location.protocol +window.location.host,也能够理解为“Domains, protocols and ports must match”)

相关配置:为了演示效果,在hosts文件里面添加以下内容html5

127.0.0.1 www.myapp.com  
127.0.0.1 sample.myapp.com  
127.0.0.1 www.otherapp.com

注意:测试demo基于NodeJSExpress4.X框架,且端口设置为80java

JSONP

JSONP也叫填充式JSON,是应用JSON的一种新方法,只不过是被包含在函数调用中的JSON(如:callback({"name", "chenjun"});)。JSONP由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数,而数据就是传入回调函数中的JSON数据git

跨域原理:利用<script>标签没有跨域限制,实现跨域目的github

访问页面:jsonp_test.ejsjson

<script>
    function dosomething(jsondata) { alert(jsondata.name + " " + jsondata.age); } </script> <script src="http://www.otherapp.com/jsonp_data?callback=dosomething"></script> 

后台路由:index.jssegmentfault

/* JSONP Test */ router.get('/jsonp_test', function(req, res) { res.render('jsonp/jsonp_test'); }); router.get('/jsonp_data', function(req, res) { var callback = req.query.callback; var data = { name: "chenjun", age: "25" }; var str = callback + '(' + JSON.stringify(data) + ')'; //jsonp res.end(str); }); 

效果:jsonp-test跨域

JSONP优缺点:

  • 优势:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中均可以运行;而且在请求完毕后能够经过调用callback的方式回传结果
  • 缺点:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种状况,不能解决不一样域的两个页面之间如何进行JS调用的问题

CORS

CORS(Cross-Origin Resource Sharing)跨域资源共享,定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。

跨域原理:CORS背后的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功仍是失败

浏览器支持状况:

  • Chrome 3+
  • Firefox 3.5+
  • Opera 12+
  • Safari 4+
  • Internet Explorer 8+

Chrome,Firefox,Opera和Safari都使用XMLHttpRequest2对象。 Internet Explorer使用了相似的XDomainRequest对象,其工做原理和XMLHttpRequest大体相同,但增长了额外的安全预防措施。

访问页面:cors_test.ejs

// 建立XHR 对象. function createCORSRequest(method, url) { var xhr = new XMLHttpRequest(); if ("withCredentials" in xhr) { // XHR for Chrome/Firefox/Opera/Safari. xhr.open(method, url, true); } else if (typeof XDomainRequest != "undefined") { // XDomainRequest for IE. xhr = new XDomainRequest(); xhr.open(method, url); } else { // 不支持CORS. xhr = null; } return xhr; } // 发起CORS请求 function makeCorsRequest() { var url = 'http://www.otherapp.com/cors_data'; var xhr = createCORSRequest('GET', url); if (!xhr) { alert('CORS not supported!'); return; } // 响应处理 xhr.onload = function() { var text = xhr.responseText; alert(text); } xhr.onerror = function() { alert('Woops, there was an error making the request.'); } xhr.send(); } makeCorsRequest(); 

后台路由:index.js

/* CORS Test */ router.get('/cors_test', function(req, res) { res.render('cors/cors_test'); }); router.get('/cors_data', function(req, res) { var data = { name: "chenjun", age: "25" }; // 设置响应头 res.setHead('Access-Control-Allow-Origin', '*'); res.end(JSON.stringify(data)); }); 

效果:cors-test

CORS优缺点:

  • 优势:支持全部类型的HTTP请求;使用普通的XMLHttpRequest发起请求和得到数据,拥有良好的出错处理
  • 缺点:老式浏览器不支持

结语

测试源码请戳这!下面一篇文章将介绍document.domainURL.hashcross-fragmentwindow.namepostMessage这五种方式的跨域实现。

参考

相关文章
相关标签/搜索