Js中的跨域问题

一、什么是跨域?

1.定义:

跨域是指从一个域名的网页去请求另一个域名的资源。比如从www.baidu.com 页面去请求 www.google.com 的资源。但是一般情况

下不能这么做,它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。跨域的严格一点的定义是:只要 协议,域名,端口

有任何一个的不同,就被当作是跨域。

**所谓同源是指,域名,协议,端口均相同。**这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,

或者通过js获取页面中不同域的框架中(iframe)的数据。

总结:只要协议、域名、端口有任何一个不同,都被当作是不同的域。

详细解释请看下图:

二、为什么浏览器要限制跨域访问

假设现在有a.com和b.com两个域,如果没有这一安全策略,那么当用户在访问a.com时,a.com的一段脚本就可以在不加载b.com的页面而随意

修改或者获取b.com上面的内容。这样将会导致b.com页面的页面发生混乱,甚至信息被获取,包括服务器端发来的session。这样的话,我们的

web世界将是一片混乱。也是因为浏览器的同源策略,保证来至不同源的对象不会互相干扰,保证了我们访问页面最基本的安全。

三、为什么要跨域?

既然有安全问题,那为什么又要跨域呢? 有时公司内部有多个不同的子域,比如一个是location.company.com ,而应用是放在app.company

.com ,这时想从 app.company.com去访问 location.company.com 的资源就属于跨域。

四、解决跨域问题的方法

(1)跨域资源共享(CORS)

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

就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。

服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域

的访问。

只需要在后台中加上响应头来允许域请求!在被请求的Response header中加入以下设置,就可以实现跨域访问了!

1//指定允许其他域名访问 2'Access-Control-Allow-Origin:*'//或指定域 3//响应类型 4'Access-Control-Allow-Methods:GET,POST' 5//响应头设置 6'Access-Control-Allow-Headers:x-requested-with,content-type'

(2)通过jsonp跨域

jsonp采用script标签的src属性实现跨域获取资源。文档中的所有带“src”属性的标签都可以跨域加载资源,而不受同源策略的限制。

例如:在浏览器中<script><img><iframe><link>等标签都可以跨域加载资源,而不受同源策略的限制。这些带“src”属性的标签在

每次加载时,实际上是由浏览器发起了一次GET请求。不同于XMLHttpRequest的是,通过src加载的资源,浏览器限制了Javascript的权限,

使其不能读、写返回内容。

XMLHttpRequest受到同源策略的约束,不能跨域访问资源。但随着跨域请求的需求越来越迫切,W3C标准制定了XMLHttpRequest跨域访问

标准:它需要通过目标域返回的HTTP头来授权是否允许跨域行为。这一跨域方案的安全基础是信任“Javascript无法控制该HTTP头”。

JSONP由两部分组成回调函数数据。回调函数是当响应到来时应该在页面中调用的函数,而数据就是传入回调函数中的JSON数据。

JSONP的原理:通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据

作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。(即用javascript动态加载一个script文件,同时定义一个callback

函数给script执行而已。)在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本

文件却是可以的,jsonp正是利用这个特性来实现的。 例如:有个a.html页面,它里面的代码需要利用ajax获取一个不同域上的json数据,

假设这个json数据地址是http://example.com/data.php,那么a.html中的代码就可以这样:

1<script type="text/javascript"> 2 function dosomething(jsondata){ 3 //处理获得的json数据 4 } 5</script> 6<script src="http://example.com/data.php?callback=dosomething"></script>

js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行

相应的配合的。

1<?php 2$callback = $_GET['callback'];//得到回调函数名 3$data = array('a','b','c');//要返回的数据 4echo $callback.'('.json_encode($data).')';//输出 5?>

最终,输出结果为:dosomething(['a','b','c']);

如果你的页面使用jquery,那么通过它封装的方法就能很方便的来进行jsonp操作了。

1<script type="text/javascript"> 2 $.getJSON('http://example.com/data.php?callback=?,function(jsondata)'){ 3 //处理获得的json数据 4 }); 5</script>

jquery自动生成一个全局函数来替换callback=?中的问号,之后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的作用。$.getJSON

方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数。

JSONP的优缺点

**JSONP的优点是:**它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,

不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。

**JSONP的缺点则是:**它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面

之间如何进行JavaScript调用的问题。

CORS和JSONP对比

CORS与JSONP相比,无疑更为先进、方便和可靠。

1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。

2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。

3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS)。

(3)通过修改document.domain来跨子域

浏览器都有一个同源策略,其限制之一就是第一种方法中我们说的不能通过ajax的方法去请求不同源中的文档。 它的第二个限制是浏览器中不

同域的框架之间是不能进行js的交互操作的。

不同的框架之间是可以获取window对象的,但却无法获取相应的属性和方法。比如,有一个页面,它的地址是http://www.example.com/a.html

在这个页面里面有一个iframe,它的src是http://example.com/b.html, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法

通过在页面中书写js代码来获取iframe中的东西的:

1<script type="text/javascript"> 2 function test(){ 3 var iframe = document.getElementById('ifame'); 4 var win = document.contentWindow;//可以获取到iframe里的window对象,但该window对象的属性和方法几乎是不可用的 5 var doc = win.document;//这里获取不到iframe里的document对象 6 var name = win.name;//这里同样获取不到window对象的name属性 7 } 8</script> 9<iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe>

这个时候,**document.domain**就可以派上用场了,我们只要把http://www.example.com/a.html 和 http://example.com/b.html这两个页面的

document.domain都设成相同的域名就可以了。但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置

自身更高一级的父域,且主域必须相同。例如:a.b.example.com 中某个文档的document.domain 可以设成a.b.example.com、

b.example.com 、example.com中的任意一个,但是不可以设成 c.a.b.example.com,因为这是当前域的子域,也不可以设成baidu.com,

因为主域已经不相同了。

1.在页面 http://www.example.com/a.html 中设置document.domain:

1<iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe> 2<script type="text/javascript"> 3 document.domain = 'example.com';//设置成主域 4 function test(){ 5 alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗口的 window 对象 6 } 7</script>

2.在页面 http://example.com/b.html 中也设置document.domain:

1<script type="text/javascript"> 2 document.domain = 'example.com';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain相同 3</script>

修改document.domain的方法只适用于不同子域的框架间的交互

(4)web sockets

web sockets是一种浏览器的API,它的目标是在一个单独的持久连接上提供全双工、双向通信。(同源策略对web sockets不适用)

web sockets原理:在js创建了web socket之后,会有一个HTTP请求发送到浏览器以发起连接。取得服务器响应后,建立的连接会使用HTTP升级

从HTTP协议交换为web sockt协议。

只有在支持web socket协议的服务器上才能正常工作。

1var socket = new WebSockt('ws://www.baidu.com');//http->ws; https->wss 2socket.send('hello WebSockt'); 3socket.onmessage = function(event){ 4 var data = event.data; 5}

 建议使用CORS解决跨域问题

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

swap空间的增减方法

(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap