同源策略:浏览器出于安全考虑,会限制文档或脚本中发起的跨域请求(但src请求不受此限)资源的加载。实际上通过抓包软件可以发现请求和响应都会成功,但是响应数据并不会被浏览器加载。不同源的客户端脚本(javascript、ActionScript)在没明确授权的情况下,不可以使用 XMLHttpRequest 对象和Fetch发起读写其他web服务器的资源,主要有如下限制:

1.) Cookie、LocalStorage 和 IndexDB 无法读取 2.) DOM 和 Js对象无法读写 3.) AJAX 请求不能发送

同源不是指脚本的来源,而是指脚本所嵌入的文档来源。具体要求域名,协议和端口都相同。

比如需要加载另一个域的一张图片资源,通过<img src='xxx'>静态引用的方式可以成功;但是通过ajax方法会报错:No 'Access-Control-Allow-Origin' header is present on the requested resource.

如果只是希望用post提交数据,不需要处理响应数据,可以:

  a.用form的submit(跨域)提交最简单,此时会导致当前页面跳转到别的域。可以将form的target设置到一个隐藏的iframe解决。

  b.用ajax的post方法,但是不能监听到响应,而且会报错。

跨域请求数据的方法:

JSONP:最简单,支持度高,但只能发送get请求,传递的参数大小有限。用js动态创建一个script标签,其中src=’www.targetweb.com?callback=foo’,然后定义foo(data)方法,最后将script标签append到页面。sript标签会自动向目标网站发送请求,服务器将数据作为参数同函数名一起返回(foo(jsonData)函数调用表达式)。实际上是返回了<script>foo(xxxx)</script>脚本文件,所以函数foo会立即调用。

//JSONP异常处理
var ele = document.createElement('script');
ele.type = "text/javascript";
ele.src = 'www.targetweb.com?callback=foo';
//异常时的回调
ele.onerror = function() {
console.log('error');
};
//js成功加载(下载并执行完之后)后的回调
ele.onload = function() {
console.log('loaded');
};
document.body.appendChild(ele);

相当于添加了如下script标签:

<script>
function foo(jsonpData){
//...
}
</script>
<script src=’www.targetweb.com?callback=foo&param1=paramSubmitByUrl’></script>
<!--后台返回的js文件实际上就是函数调用:foo(jsonpData) -->

jQuery中的跨域请求

$.ajax({
type : "get",
async:true,
url : "/taotao-rest/category", //跨域的请求地址
crossDomain:true,
dataType : "jsonp",
jsonp: "callbackName",//(不必要)定义请求参数名(相当于表单的name),供后台获取参数使用,默认为"&callback=?"中的callback
jsonpCallback:"showLists",//(不必要)自定义jsonp回调函数名称,默认为jQuery自动生成的随机函数名替代上述?号;在本例中后台应该返回showLists(jsonData)
success : function(json){
//为什么不定义jsonpCallback也不会报错?因为jQuery内部会自定义jsonpCallback(若无),并用responseContainer接受后台返回的数据再存入json变量中。
//window[ callbackName ] = function() {
// responseContainer = arguments;
//};
//最后jQuery之后会将callBackName和对应的script标签删除
//所以此时才可以直接用json数据
},
beforeSend: function(){
//jsonp方式时此方法不会触发,因为不是用 XHR发送的请求
},
error: function(xhr){
//jsonp 方式时此方法不会触发
}
});

H5的WebSocket:使用ws和wss作为协议,允许跨域通信,可以相互推送信息。

iframe方式
因为jsonp只能发送get请求,所以对于跨域post提交大量数据时无能为力,此时可以用iframe跨域提交post请求。(兼容性好,兼容ie7/8/9)

<iframe>元素表示嵌套的浏览上下文,可以有效地将另一个HTML页面嵌入到当前页面中。实践中常将form表单的target设置为iframe的name属性,这样submit提交后服务器返回的页面就会在iframe中显示,主页面不会再刷新。iframe常用属性:

name属性
嵌入的iframe的名称,该名称可以用作<a>标签的target属性值,在指定的框架中打开被链接文档;也可用作<form>标签的target属性值,规定在何处打开action URL。或<input>/<button>标签的formtaget属性值,规定表示提交表单后在哪里显示接收到响应的名称或关键词,formtarget 属性会覆盖 <form> 元素的 target 属性。

src
规定在 iframe 中显示的文档的 URL。

与iframe的交互:
  在主页面获取iframe内的文档对象:document.getElementById('childiframe').contentDocument.xxx
  在iframe中的脚本访问主页面的window的属性:window.parent.document
  在主页面访问iframe中window里的属性:document.getElementById('childiframe').contentWindow
注意:如果iframe和主页面不在同一个域,则不能通过js互相访问(window或DOM),被浏览器限制了。把两个子页面的document.domain都指向主域则可以互相访问。 

iframe的弊端
window 的 onload 事件需要在iframe 的所有资源加载完毕才会触发,另外会占用主页面的可用连接数量。所以一般尽量少用iframe,要用的话最好等主页面加载完后再设置iframe的src加载内容。

使用iframe跨域

主要是利用Window.name属性传递数据。每个iframe都有window对象,其name属性用于标记window的名字,可以存贮2M大小的数据。除非主动修改或关闭,同一个window打开任意页面其值都不变。window.name和iframe.name是2个概念,初始化时window.name会默认取当前iframe的name的值,但是之后就无关联。修改window.name不影响iframe.name。只有在DOM对象下可以修改iframe的name属性。另外在设置a元素和form表单的target属性时,window.name优先于iframe.name。

步骤:

1.使用post提交数据

  使用主页面的form跨域提交post数据,target指定到隐藏的iframe;或者在隐藏的iframe中用ajax提交post数据;

2.服务器端返回跨域下的任意空文档,script部分需要设置window.name=data,data为服务器响应的数据。

3.将iframe的src设置为主页面的域,否则无法访问iframe的window。之后再从iframe的contentWindow.name中取数据。

//主页面
var isloaded=false; //防止循环刷新iframe
//chrome和ie下onload事件的触发时机不一样?!!!
document.getElementById('iframe0').onload=function (e) {
if(!isloaded){
isloaded=true;
e.target.src='null.html';//设主页面同域的任意页面,响应数据在脚本中
}else{
//使用跨域获取的数据
  console.log(document.getElementById('iframe0').contentWindow.name);
}
}

CORS(Cross-origin resource sharing)跨域资源共享
如果只需要兼容IE11,则可以使用CORS。服务器实现CORS接口(在header配置Access-Control-Allow-origin属性),浏览器不会丢弃响应,就可以跨源通信了。

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true);
xhr.withCredentials = true;

websocket协议跨域

跨域方法:JSONP、iframe的更多相关文章

  1. JS跨域:jsonp、跨域资源共享、iframe+window.name

    JS跨域:jsonp.跨域资源共享.iframe+window.name :https://www.cnblogs.com/doudoublog/p/8652213.html JS中的跨域 请求跨域有 ...

  2. js中几种实用的跨域方法原理详解(转)

    今天研究js跨域问题的时候发现一篇好博,非常详细地讲解了js几种跨域方法的原理,特分享一下. 原博地址:http://www.cnblogs.com/2050/p/3191744.html 下面正文开 ...

  3. js中几种实用的跨域方法原理详解

    这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...

  4. 前端Js跨域方法汇总—剪不断,理还乱,是跨域

    1.通过jsonp跨域2.通过修改document.domain来跨子域(iframe)3.隐藏的iframe+window.name跨域4.iframe+跨文档消息传递(XDM)5.跨域资源共享 C ...

  5. 循序渐进Python3(十一) --6--  Ajax 实现跨域请求 jsonp 和 cors

    Ajax操作如何实现跨域请求?       Ajax (XMLHttpRequest)请求受到同源策略的限制.       Ajax通过XMLHttpRequest能够与远程的服务器进行信息交互,另外 ...

  6. JS跨域方法及原理

        JS跨域分析判断 JS跨域:在不同域之间,JS进行数据传输或通信.比如ajax向不同的域请求数据.JS获取iframe中的页面中的值(iframe内外不同域) 只要协议.端口.域名有一个不同则 ...

  7. [转]js中几种实用的跨域方法原理详解

    转自:js中几种实用的跨域方法原理详解 - 无双 - 博客园 // // 这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同 ...

  8. 百度的一个Ajax跨域方法 JavaScript是没有域的限制

    baidu的通行证处理都是在二级域名passport.baidu.com中处理的,但是baidu很多地方登录都好像是用ajax处理的,他是怎么做的呢?研究了一下,发现一个小技巧. 在http://zh ...

  9. JavaScript 跨域方法总结

    同源策略 在客户端编程语言中,如javascript和 ActionScript,同源策略是一个很重要的安全理念,它在保证数据的安全性方面有着重要的意义.同源策略规定跨域之间的脚本是隔离的,一个域的脚 ...

  10. js中几种实用的跨域方法原理详解【转】

    源地址:http://www.cnblogs.com/2050/p/3191744.html 这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通 ...

随机推荐

  1. 基于Django+celery二次开发动态配置定时任务 ( 二)

    一.需求 结合上一篇,使用djcelery模块开发定时任务时,定时任务的参数都保存在djcelery_periodictask表的args.kwargs字段里,并且是json格式.那么,当定时任务多了 ...

  2. Python中 '==' 与'is' 以及它们背后的故事

    摘要 比较判断逻辑是在代码中经常使用的,在Python中常用 '==' 和 is 来做比较判断. ==  :  双等号是用来比较变量所指向内存单元中的值是否相等,它只关心值,并不在意值的内存地址,也就 ...

  3. 48.rocketMQ

    一.简介 RocketMQ是阿里旗下的一款产品,分为开源版本和非开源版本.相比于ActiveMQ,RocketMQ支持顺序消费.事务机制.失败重试机制.消息可查询.消息订阅.较强的水平扩展能力.亿级堆 ...

  4. 2016级算法期末上机-C.简单·Bamboo's Fight with DDLs III

    简单·Bamboo's Fight with DDLs III 分析 一句话:贪心,简单哈夫曼应用,要求的其实是所有结点的值与权值的乘积之和,也就是带权路径长. 可以理解为非叶子节点的权值的和,这里的 ...

  5. C#-WebForm-★★★JQuery知识——基础知识、选择器、事件★★★

    JQuery 与 JS 之间的转换 将JQuery转换为JS —— get(0) 例如:alert( $("#d1").get(0).offsetwidth ); 将JS 转换为J ...

  6. java内存的分配策略

    1.概述 本文是<深入理解java虚拟机>(周志明著)3.6节的笔记整理,文章结构也与书上相同,讲述的是几条最普遍的内存分配策略. 2.对象优先在Eden分配 ** 大多数情况下,对象在新 ...

  7. HLS:OpenCV和RTL代码转换关系

    OpenCV 图像处理是基于存储器帧缓存而构建的, 它总是假设视频帧数据存放在外部 DDR 存储器中. 由于处理器的小容量高速缓存性能的限制, 因此, OpenCV 访问局部图像性能较差. 并且, 从 ...

  8. Visual Studio 跨平台開發實戰(3) - Xamarin iOS 多頁面應用程式開發 (转帖)

    前言 在前一篇教學中, 我們學會如何使用Visual Studio 搭配Xcode 進行iOS基本控制項的操作. 但都是屬於單一畫面的應用程式. 這次我們要來練習如何透過Navigation Cont ...

  9. ECharts概念学习系列之ECharts是什么?

    不多说,直接上干货! http://echarts.baidu.com/index.html http://echarts.baidu.com/echarts2/index.html 开源的EChar ...

  10. WPF 将TextBox更改为PasswordBox样式(文字显示方式为密码)

    在TextBox样式中增加如下所诉: <Style x:Key="TxtPwd" TargetType="{x:Type TextBox}"> &l ...