若是两个页面的协议,端口(若是有指定)和域名都相同,则两个页面具备相同的源。javascript
下表给出了相对http://store.company.com/dir/page.html
同源检测的示例:html
同源策略限制了从同一个源加载的文档或脚本如何与来自另外一个源的资源进行交互。前端
容许跨源访问的一些例子:java
<script src="..."></script>
标签嵌入跨域脚本。语法错误信息只能在同源脚本中捕捉到。<link rel="stylesheet" href="...">
标签嵌入CSS。因为CSS的松散的语法规则,CSS的跨域须要一个设置正确的Content-Type
消息头。不一样浏览器有不一样的限制: IE, Firefox, Chrome, Safari (跳至CVE-2010-0051)部分 和 Opera。<img>
嵌入图片。支持的图片格式包括PNG,JPEG,GIF,BMP,SVG,...<video>
和 <audio>
嵌入多媒体资源。<object>
, <embed>
和 <applet>
的插件。@font-face
引入的字体。一些浏览器容许跨域字体( cross-origin fonts),一些须要同源字体(same-origin fonts)。<frame>
和 <iframe>
载入的任何资源。站点可使用X-Frame-Options消息头来阻止这种形式的跨域交互。使用 CORS 容许跨源访问。jquery
跨源脚本API的访问git
Javascript的APIs中,如 iframe.contentWindow
, window.parent
, window.open
和 window.opener
容许文档间直接相互引用。当两个文档的源不一样时,这些引用方式将对 Window 和 Location对象的访问添加限制。github
可使用window.postMessage做不一样源文档之间的交流。
web
跨源数据存储访问ajax
存储在浏览器中的数据,如localStorage和IndexedDB,以源进行分割。每一个源都拥有本身单独的存储空间,一个源中的Javascript脚本不能对属于其它源的数据进行读写操做。chrome
一、JSONP
Jsonp(JSON with Padding) 是 json 的一种"使用模式",可让网页从别的域名(网站)那获取资料,即跨域读取数据。
Jsonp 的实现原理是利用 <script> 标签能够获取不一样源资源的特色,来达到跨域访问某个资源的目的。假如 <script> 元素内部的代码没有位于某个函数中,那么这些代码会在页面被加载时被当即执行。
应用实例:
服务端代码使用jFinal框架
1 package com.controller; 2 3 import com.mazu.core.Controller; 4 5 public class JsonPController extends Controller{ 6 7 public void getUserInfo(){ 8 9 String userId = getPara("userId"); 10 String callBackFunc = getPara("callback"); 11 if(userId!=null&&userId.equals("123")){ 12 String userJson = "{\"userName\":\"Admin\",\"age\":26}"; 13 callBackFunc += "('success',"+userJson+")";//拼接为callback(a,b)的形式返回给前端 14 renderJson(callBackFunc); 15 }else{ 16 renderJson(callBackFunc+"('error')"); 17 } 18 } 19 }
客户端代码
1 <script> 2 function callbackFunc(status,data){ 3 if(status=="success"){ 4 console.log(data.userName+":"+data.age); 5 }else{ 6 console.log(status); 7 } 8 } 9 </script> 10 <script type="text/javascript" src="http://localhost/TestJSONP/jsonp/getUserInfo?userId=123&callback=callbackFunc"></script>
chrome中执行结果
因为是本地测试,使用的是端口不一样的两个项目,能够看到服务端响应后,返回给前端一个字符串callback(status,data),前端<script>接收到这段代码后当即执行,成功实现了跨域资源的访问。
在jQuery中如何经过JSONP来跨域获取数据
第一种方法是在ajax函数中设置dataType为'jsonp':
$.ajax({
dataType: 'jsonp',
url: 'http://localhost/TestJSONP/jsonp/getUserInfo?userId=123',
success: function(data){
console.log(data);//success
}
});
上面的方式只能返回一个参数,多参数时将没法获得第二个及以后的参数。
能够在传递过程当中自定义函数名,使用jsonpCallback参数
jsonp:表示传递的参数,默认为callback,咱们也能够自定义
jsonpCallback:表示传递的参数值,也就是回调的函数名称,这是自定义的名称
1 <script src="http://apps.bdimg.com/libs/jquery/1.8.3/jquery.js"></script> 2 <script> 3 function callbackFunc(status,data){ 4 if(status=="success"){ 5 // console.log(data.userName+":"+data.age); 6 console.log("callback:"+data); 7 }else{ 8 console.log("callback:"+status); 9 } 10 } 11 $.ajax({ 12 type:"get", 13 url: 'http://localhost/TestJSONP/jsonp/getUserInfo?userId=123', 14 dataType: 'jsonp', 15 jsonp:'callback', 16 jsonpCallback:'callbackFunc', 17 success: function(data){ 18 console.log("ajax:"+data); 19 } 20 }); 21 22 </script>
执行结果:
能够看到返回结果中,仍然获取不到第二个参数值。仔细debug了一下后台,返回的字符串也是正确的。
因而我改了下后台的返回值和回调函数的参数,获得了正确的测试结果。
因而可知,使用jQuery作JSONP跨域调用时,与ajax的success回调函数同样,服务端须要将传的内容封装在一个返回值中。
为何使用jsonpCallback简单的绑定回调函数就能实现回调函数调用了呢?
仔细跟踪chrome中的执行过程,发现Jquery首先将回调函数赋值给一个内部函数,在服务端响应成功后,执行这个内部函数,而后销毁,起到一个临时代理的做用。
jQuery 的 $.ajax 只支持get方式获取跨域数据,而且它不支持出错时的回调。
jQuery-JSONP是一个支持 JSONP 调用的 jQuery 插件,使用它是由于它支持出错时的 ajax 回调。
1 <script src="jquery-3.2.1.js"></script> 2 <script src="jquery-jsonp.js"></script> 3 <script> 4 $.jsonp({ 5 url: 'http://localhost/TestJSONP/jsonp/getUserInfo', 6 data: { userId: 123 }, 7 callbackParameter: "callback", 8 success: function (data, textStatus, xOptions) { 9 console.log(data); 10 }, 11 error: function (xOptions, textStatus) { 12 } 13 }); 14 </script>
第1个须要注意的地方是 callbackParameter,若是没有专门的 callback 函数,必定要写上 "callback";
第2个须要注意的地方是在 success 回调函数中,xOptions包含传给服务器的参数,如xOptions.data={userId:123}。
二、CORS
CORS全称是“跨域资源共享”(Cross-origin resource sharing),它是一种经过设置HTTP头信息来获取跨源服务器上的特定资源,主要是设置Access-Control-Allow-Origin字段的值。
服务端代码:
1 public void getUserInfo(){ 2 3 String userId = getPara("userId"); 4 String userJson = ""; 5 if(userId!=null&&userId.equals("123")){ 6 System.out.println("userId:"+userId); 7 userJson = "{\"userName\":\"Admin\",\"age\":26}"; 8 } 9 //getResponse().setHeader("Access-Control-Allow-Origin", "*"); 10 renderJson(userJson); 11 12 }
客户端代码:
1 $.ajax({ 2 type:"get", 3 url: 'http://localhost/TestJSONP/jsonp/getUserInfo?userId=123', 4 dataType: 'json', 5 success: function(data){ 6 console.log("ajax:"+data); 7 } 8 })
当服务端回应头信息中没有包含Access-Control-Allow-Origin
字段时,浏览器报错以下:
设置Access-Control-Allow-Origin为*,表示接受任意域名的请求,在实际开发中为了安全起见通常设为特定域名。
与JSONP的比较
CORS与JSONP的使用目的相同,可是比JSONP更强大。
JSONP只支持GET
请求,CORS支持全部类型的HTTP请求。JSONP的优点在于支持老式浏览器,以及能够向不支持CORS的网站请求数据。
三、window.postMessage
HTML5跨文档消息传输Cross Document Messaging。下一代浏览器都将支持这个功能:Chrome 2.0+、Internet Explorer 8.0+, Firefox 3.0+, Opera 9.6+, 和 Safari 4.0+ 。
用postMessage支持基于web的实时消息传递。
window.postMessage() 方法被调用时,会在全部页面脚本执行完毕以后(e.g., 在该方法以后设置的事件、以前设置的timeout 事件,etc.)向目标窗口派发一个 MessageEvent
消息。
该MessageEvent
消息有四个属性须要注意:
语法:
otherWindow.postMessage(message, targetOrigin, [transfer]);
参考: