详解5种跨域方式及其原理

同源定义

如果两个页面拥有相同的协议(protocol),端口(如果指定),和主机,那么这两个页面就属于同一个源(origin)。

以下是同源检测的示例


URL


结果


原因


http://store.company.com/dir2/other.html


Success


http://store.company.com/dir/inner/another.html


Success


https://store.company.com/secure.html


Failure


协议不同


http://store.company.com:81/dir/etc.html


Failure


端口不同


http://news.company.com/dir/other.html


Failure


主机不同

1.jsonp

script标签是不受同源策略影响的,它可以引入来自任何地方的js文件。

而jsonp的原理就是,在客户端和服务端定义一个函数,当客户端发起一个请求时,服务端返回一段JavaScript代码,其中调用了在客户端定义的函数,并将相应的数据作为参数传入该函数。

function jsonp_cb(data)
{

console.log(data);

}

function ajax(){

var url
= "http://xx.com/test.PHP?jsonp_callback=jsonp_cb";

var script
= document.createElement(‘script‘);

// 发送请求

script.src
= url;

document.head.appendChild(script);

}

ajax()

服务端获取到jsonp_callback传递的函数名jsonp_cb,返回一段对该函数调用的js代码

jsonp_cb({

"name":
"story"

});

2.img ping

img标签也是没有跨域限制的,但它只能用来发送GET请求,且无法获取服务端的响应文本,可以利用它实现一些简单的、单向的跨域通信,例如跟踪用户的点击

var img =
new Image();

img.onload
= function(){

console.log(‘done‘)

img.onload
= null;

img =
null;

}

img.src
= "http://xx/xx.gif"

3.window.name

window对象拥有name属性,它有一个特点:相同协议下,在一个页面中,不随URL的改变而改变

示例代码

window.name
= ‘string‘
// 字符串,一般允许的最大值为2M

console.log(window.name)

location =
‘http://funteas.com/‘

此时,在控制台输入window.name,结果依然是”string”

window.name
// "string"

window.name的值只能是字符串,任何其他类型的值都会“转化”为字符串

例如

window.name
= function(){}

console.log(window.name)

// "function(){}"

通过window.name实现跨域也很简单,iframe拥有contentWindow属性,其指向该iframe的window对象的引用,如果在iframe的src指向的页面中设置window.name值,那么就可以通过iframe.contentWindow.name就可以拿到这个值了

var url =
"http://funteas.com/lab/windowName";

var iframe = document.createElement(‘iframe‘)

iframe.onload
= function(){

var data
= iframe.contentWindow.name

console.log(data)

}

iframe.src
= url

document.body.appendChild(iframe)

然而,chrome会提示你跨域了!

而我们已经知道window.name不随URL的改变而改版,也就是说,onload时,已经获取到了name,只不过因为不同源,当前页面的脚本无法拿到iframe.contentWindow.name,此时只需要把iframe.src改为同源即可

var url =
"http://funteas.com/lab/windowName";

var iframe = document.createElement(‘iframe‘)

iframe.onload
= function(){

iframe.src
= ‘favicon.ico‘;

var data
= iframe.contentWindow.name

console.log(data)

}

iframe.src
= url

document.body.appendChild(iframe)

刷新页面,你会发现iframe不断刷新,这是因为每次onload,iframe的src被修改,然后再次触发onload,从而导致iframe循环刷新,修改下即可

var url =
"http://funteas.com/lab/windowName";

var iframe = document.createElement(‘iframe‘)

var state =
true;

iframe.onload
= function(){

if(state
=== true){

iframe.src
= ‘favicon.ico‘;

state =
false;

}else
if(state
=== false){

state =
null

var data
= iframe.contentWindow.name

console.log(data)

}

}

iframe.src
= url

document.body.appendChild(iframe)

上面请求的是一个静态页面,而服务端通常需要的是动态数据

echo ‘<script> window.name = "{\"name\":\"story\"}"</script>‘;

4.postMessage

postMessage允许不同源之间的脚本进行通信,用法

otherWindow.postMessage(message, targetOrigin);

  • otherWindow 引用窗口 iframe.contentwindow 或 window.open返回的对象
  • message 为要传递的数据
  • targetOrigin 为目标源

// http://127.0.0.1:80

var iframe = document.createElement(‘iframe‘)

iframe.onload
= function(){

var popup
= iframe.contentWindow

popup.postMessage("hello",
"http://127.0.0.1:5000");

}

iframe.src
= ‘http://127.0.0.1:5000/lab/postMessage‘

document.body.appendChild(iframe)

// 监听返回的postMessage

window.addEventListener("message",
function(event){

if
(event.origin
!== "http://127.0.0.1:5000")
return;

console.log(event.data)

}, false)

// http://127.0.0.1:5000/lab/postMessage

window.addEventListener("message",
function(event){

// 验证消息来源

if
(event.origin
!== "http://127.0.0.1")
return;

console.log(event.source);
// 消息源 popup

console.log(event.origin);
// 消息源URI https://secure.example.NET

console.log(event.data);
// 来自消息源的数据 hello

// 返回数据

var message
= ‘world‘;

event.source.postMessage(message,
event.origin);

}, false);

5.CORS

CORS(跨域资源共享)是一种跨域访问的机制,可以让AJAX实现跨域访问。它允许一个域上的脚本向另一个域提交跨域 AJAX 请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。

Access-Control-Allow-Origin:
* // 允许来自任何域的请求

Access-Control-Allow-Origin: http://funteas.com/
// 仅允许来自http://funteas.com/的请求

当客户端的ajax请求的url为其他域时,对于支持CORS的浏览器,请求头会自动添加Origin,值为当前host

var xhr =
new XMLHttpRequest();

var url =
‘http://bar.other/resources/public-data/‘;

xhr.open(‘GET‘, url,
true);

xhr.send();

CORS默认不发送cookie,如果要发送cookie,需要设置withCredentials

var xhr =
new XMLHttpRequest();

xhr.withCredentials
= true;

同时,服务端也要设置

Access-Control-Allow-Credentials:
true

查看MDN关于CORS的介绍【https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS】

时间: 2024-11-07 10:25:28

详解5种跨域方式及其原理的相关文章

JavaScript 九种跨域方式实现原理

前言 前后端数据交互经常会碰到请求跨域,什么是跨域,以及有哪几种跨域方式,这是本文要探讨的内容. 一.什么是跨域? 1.什么是同源策略及其限制内容? 同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到 XSS.CSFR 等***.所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个 ip 地址,也非同源.同源策略限制内容有: Cookie.LocalStorage.IndexedDB 等存储性内容DOM 节点AJAX 请求发送

九种跨域方式实现原理

前言 前后端数据交互经常会碰到请求跨域,什么是跨域,以及有哪几种跨域方式,这是本文要探讨的内容. 本文完整的源代码请猛戳github 博客 一.什么是跨域? 1.什么是同源策略及其限制内容? 同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到 XSS.CSFR 等攻击.所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个 ip 地址,也非同源. 同源策略限制内容有: Cookie.LocalStorage.IndexedDB

sas数据读取详解 四种读取数据方式以及数据指针的位置 、读取mess data的两个小工具、特殊的读取技巧、infile语句及其选项(dsd dlm missover truncover obs firstobs)、proc import、自定义缺失值

(The record length is the number of characters, including spaces, in a data line.) If your data lines are long, and it looks like SAS is not reading all your data, then use the LRECL= option in the INFILE statement to specify a record length at least

10月10日 jsonp的三种跨域方式

1.通过jq的$.ajax()完成跨域,这是我比较喜欢的一种方式. 代码如下: $.ajax({ type:'get', async:true, url:'地址', dataType:'jsonp',   //这里一定要写 jsonp:'callback', jsonCallback:'自定义的一个名字', success:function(data){ console.log(data); }, error:function(data){ console.log(‘错误’) } }) 2.通过

jsonp详解—javasript/jQuery跨域请求

json相信大家都用的多,jsonp我就一直没有机会用到,但也经常看到,只知道是"用来跨域的",一直不知道具体是个什么东西.今天总算搞明白了.下面一步步来搞清楚jsonp是个什么玩意. 同源策略 首先基于安全的原因,浏览器是存在同源策略这个机制的,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性.看起来不知道什么意思,实践一下就知道了. 1.随便建两个网页 一个端口是2698,一个2701,按照定义它们是不同源的. 2.用jQuery发起不同源的请求 在2698端

偶然发现了另一种跨域方式,不知道有没有人这么玩过

众所周知,jsonp利用浏览器不限制加载跨域外部资源的特性,使用script标签src属性请求接口,加载数据,在script中触发提前声明好的函数拿到数据,前端的前辈们这一手操作简直就是犀利. 其实实现单向的接口调用使用任何资源标签都可以实现,关键在于如何取到后端传回的数据实现双向交互.现代浏览器提供了getComputedStyle这个API,使得通过js可以拿到某个元素最终应用的css样式.(低版本IE中为currentStyle).如下所示: 如此一来,我们就可以在css样式中取得想要的数

解决ajax跨域的方法原理详解之Cors方法

1.神马是跨域(Cross Domain) 对于端口和协议的不同,只能通过后台来解决. 一句话:同一个ip.同一个网络协议.同一个端口,三者都满足就是同一个域,否则就是 跨域问题了.而为什么开发者最初不直接定为一切可跨域的呢?默认的为什么都是不可跨域呢?这就涉及到了同源策 略,为了系统的安全,由Netscape提出一个著名的安全策略.现在所有支持JavaScript的浏览器都会使用这个策略. 所谓同源是,域名,协议,端口相同.当我们在浏览器中打开百度和谷歌两个网站时,百度浏览器在执行一个脚本的

转:Windows下的PHP开发环境搭建——PHP线程安全与非线程安全、Apache版本选择,及详解五种运行模式。

原文来自于:http://www.ituring.com.cn/article/128439 Windows下的PHP开发环境搭建——PHP线程安全与非线程安全.Apache版本选择,及详解五种运行模式. 今天为在Windows下建立PHP开发环境,在考虑下载何种PHP版本时,遭遇一些让我困惑的情况,为了解决这些困惑,不出意料地牵扯出更多让我困惑的问题. 为了将这些困惑一网打尽,我花了一下午加一晚上的时间查阅了大量资料,并做了一番实验后,终于把这些困惑全都搞得清清楚楚了. 说实话,之所以花了这么

web三种跨域请求数据方法

web三种跨域请求数据方法 以下测试代码使用php,浏览器测试使用IE9,chrome,firefox,safari <!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.min.