- 浏览: 505795 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (155)
- jQuery (12)
- java基础 (21)
- hibernate错误 (2)
- myeclipse快捷键 (1)
- hibernate (5)
- javaWeb (1)
- tomcat (4)
- oracle (7)
- 用命令导入导出数据库 (1)
- ssh整合类 (2)
- struts2 (7)
- spring (0)
- html (3)
- xml操作 (1)
- linux (4)
- cad (1)
- log4j日志配置 (4)
- MyEclipse (8)
- struts1 (3)
- 正则表达式 (3)
- struts标签 (1)
- poderdesinger (1)
- javascript (10)
- linux 客户端 (2)
- webProjectProblem (4)
- sql 问题 (1)
- 文件下载问题 (1)
- js正则表达式 (1)
- java 乱码问题 (1)
- mysql (6)
- 生活随笔 (3)
- 文件上传 (3)
- 电影 (1)
- json (1)
- 理论概念 (1)
- 总结 (1)
- ssh项目错误 (2)
- sql (3)
- powerdesinger (1)
- 导入exce数据 (1)
- windows cmd命令 (1)
- weblogic (1)
- 分页功能 (1)
- ssh 问题 (1)
- 项目问题积累总结 (5)
- 发散思维 (1)
- idea (1)
最新评论
-
tecwang:
DiskFileItemFactory类 -
Yimmm:
DiskFileItemFactory类 -
qmgrx2007:
引用
DiskFileItemFactory类 -
逆风翔:
校验特殊字符中的—再校验到 含有字符mda ...
js中用正则表达式 过滤特殊字符 ,校验所有输入域是否含有特殊符号 -
pineapple_zjw:
谢谢分享 学习ing
java拼接和解析json
js跨域 所谓的域值的就是“域名”
原帖地址:http://itgeeker.com/mathml/readpaper?pid=53
<!--StartFragment -->
JavaScript是一种在Web开发中经常使用的前端动态脚本技术。在JavaScript中,有一个很重要的安全性限制,被称为“Same- Origin Policy”(同源策略)。这一策略对于JavaScript代码能够访问的页面内容做了很重要的限制,即JavaScript只能访问与包含它的文档在同一域下的内容。
JavaScript这个安全策略在进行多iframe或多窗口编程、以及Ajax编程时显得尤为重要。根据这个策略,在baidu.com下的页面中包含的JavaScript代码,不能访问在google.com域名下的页面内容;甚至不同的子域名之间的页面也不能通过JavaScript代码互相访问。对于Ajax的影响在于,通过XMLHttpRequest实现的Ajax请求,不能向不同的域提交请求,例如,在 abc.example.com下的页面,不能向def.example.com提交Ajax请求,等等。
然而,当进行一些比较深入的前端编程的时候,不可避免地需要进行跨域操作,这时候“同源策略”就显得过于苛刻。本文就这个问题,概括了跨域所需要的一些技术。
下面我们分两种情况讨论跨域技术:首先讨论不同子域的跨域技术,然后讨论完全不同域的跨域技术。
(一)不同子域的跨域技术。
我们分两个问题来分别讨论:第一个问题是如何跨不同子域进行JavaScript调用;第二个问题是如何向不同子域提交Ajax请求。
先来解决第一个问题,假设example.com域下有两个不同子域:abc.example.com和def.example.com。现在假设在def.example.com下面有一个页面,里面定义了一个JavaScript函数:
- function funcInDef() {
- .....
- }
function funcInDef() { ..... }
我们想在abc.example.com下的某个页面里调用上面的函数。再假设我们要讨论的abc.example.com下面的这个页面是以iframe形式嵌入在def.example.com下面那个页面里的,这样我们可能试图在iframe里做如下调用:
window.top.funcInDef();
好,我们注意到,这个调用是被前面讲到的“同源策略”所禁止的,JavaScript引擎会直接抛出一个异常。
为了实现上述调用,我们可以通过修改两个页面的domain属性的方法做到。例如,我们可以将上面在abc.example.com和def.example.com下的两个页面的顶端都加上如下的JavaScript代码片段:
- < script type = "text/javascript" >
- document.domain = "example.com" ;
- </ script >
<script type="text/javascript"> document.domain = "example.com"; </script>
这样,两个页面就变为同域了,前面的调用也可以正常执行了。
这里需要注意的一点是,一个页面的document.domain属性只能设置成一个更顶级的域名(除了一级域名),但不能设置成比当前域名更深层的子域名。例如,abc.example.com的页面只能将它的domain设置成example.com,不能设置成 sub.abc.example.com,当然也不能设置成一级域名com。
上面的例子讨论的是两个页面属于iframe嵌套关系的情况,当两个页面是打开与被打开的关系时,原理也完全一样。
下面我们来解决第二个问题:如何向不同子域提交Ajax请求。
通常情况下,我们会用与下面类似的代码来创建一个XMLHttpRequest对象:
- factories = [
- function () { return new XMLHttpRequest(); },
- function () { return new ActiveXObject( "Msxml2.XMLHTTP" ); },
- function () { return new ActiveXObject( "Microsoft.XMLHTTP" ); }
- ];
- function newRequest() {
- for ( var i = 0; i < factories.length; i++) {
- try {
- var factory = factories[i];
- return factory();
- } catch (e) {}
- }
- return null ;
- }
factories = [ function() { return new XMLHttpRequest(); }, function() { return new ActiveXObject("Msxml2.XMLHTTP"); }, function() { return new ActiveXObject("Microsoft.XMLHTTP"); } ]; function newRequest() { for(var i = 0; i < factories.length; i++) { try{ var factory = factories[i]; return factory(); } catch(e) {} } return null; }
上面的代码中引用ActiveXObject,是为了兼容IE6系列浏览器。每次我们调用newRequest函数,就获得了一个刚刚创建的 Ajax对象,然后用这个Ajax对象来发送HTTP请求。例如,下面的代码向abc.example.com发送了一个GET请求:
- var request = newRequest();
- request.open("GET" , "http://abc.example.com" );
- request.send(null );
var request = newRequest(); request.open("GET", "http://abc.example.com" ); request.send(null);
假设上面的代码包含在一个abc.example.com域名下的页面里,则这个GET请求可以正常发送成功,没有任何问题。然而,如果现在要向def.example.com发送请求,则出现跨域问题,JavaScript引擎抛出异常。
解决的办法是,在def.example.com域下放置一个跨域文件,假设叫crossdomain.html;然后将前面的 newRequest函数的定义移到这个跨域文件中;最后像之前修改document.domain值的做法一样,在crossdomain.html文件和abc.example.com域下调用Ajax的页面顶端,都加上:
- < script type = "text/javascript" >
- document.domain = "example.com" ;
- </ script >
<script type="text/javascript"> document.domain = "example.com"; </script>
为了使用跨域文件,我们在abc.example.com域下调用Ajax的页面中嵌入一个隐藏的指向跨域文件的iframe,例如:
- < iframe name = "xd_iframe" style = "display:none" src = "http://def.example.com/crossdomain.html" >
- </ iframe >
<iframe name="xd_iframe" style="display:none" src="http://def.example.com/crossdomain.html"> </iframe>
这时abc.example.com域下的页面和跨域文件crossdomain.html都在同一个域(example.com)下,我们可以在abc.example.com域下的页面中去调用crossdomain.html中的newRequest函数:
- var request = window.frames[ "xd_iframe" ].newRequest();
var request = window.frames["xd_iframe"].newRequest();
这样获得的request对象,就可以向http://def.example.com发送HTTP请求了。
(二)完全不同域的跨域技术。
如果顶级域名都不相同,例如example1.com和example2.com之间想通过JavaScript在前端通信,则所需要的技术更复杂些。
在讲解不同域的跨域技术之前,我们首先明确一点,下面要讲的技术也同样适用于前面跨不同子域的情况,因为跨不同子域只是跨域问题的一个特例。当然,在恰当的情况下使用恰当的技术,能够保证更优的效率和更高的稳定性。
简言之,根据不同的跨域需求,跨域技术可以归为下面几类:
- JSONP跨域GET请求
- 通过iframe实现跨域
- flash跨域HTTP请求
- window.postMessage
下面详细介绍各种技术。
1. JSONP。
利用在页面中创建<script>节点的方法向不同域提交HTTP请求的方法称为JSONP,这项技术可以解决跨域提交Ajax请求的问题。JSONP的工作原理如下所述:
假设在http://example1.com/index.php这个页面中向http://example2.com/getinfo.php 提交GET请求,我们可以将下面的JavaScript代码放在http://example1.com/index.php这个页面中来实现:
- var eleScript= document.createElement( "script" );
- eleScript.type = "text/javascript" ;
- eleScript.src = "http://example2.com/getinfo.php" ;
- document.getElementsByTagName("HEAD" )[0].appendChild(eleScript);
var eleScript= document.createElement("script"); eleScript.type = "text/javascript"; eleScript.src = "http://example2.com/getinfo.php"; document.getElementsByTagName("HEAD")[0].appendChild(eleScript);
当GET请求从http://example2.com/getinfo.php返回时,可以返回一段JavaScript代码,这段代码会自动执行,可以用来负责调用http://example1.com/index.php页面中的一个callback函数。
JSONP的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。
JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
2. 通过iframe实现跨域。
iframe跨域的方式,功能强于JSONP,它不仅能用来跨域完成HTTP请求,还能在前端跨域实现JavaScript调用。因此,完全不同域的跨域问题,通常采用iframe的方式来解决。
与JSONP技术通过创建<script>节点向不同的域提交GET请求的工作方式类似,我们也可以通过在 http://example1.com/index.php页面中创建指向http://example2.com/getinfo.php的 iframe节点跨域提交GET请求。然而,请求返回的结果无法回调http://example1.com/index.php页面中的 callback函数,因为受到“同源策略”的影响。
为了解决这个问题,我们需要在example1.com下放置一个跨域文件,比如路径是http://example1.com/crossdomain.html。
当http://example2.com/getinfo.php这个请求返回结果的时候,它大体上有两个选择。
第一个选择是,它可以在iframe中做一个302跳转,跳转到跨域文件http://example1.com /crossdomain.html,同时将返回结果经过URL编码之后作为参数缀在跨域文件URL后面,例如http://example1.com /crossdomain.html?result=<URL-Encoding-Content>。
另一个选择是,它可以在返回的页面中再嵌入一个iframe,指向跨域文件,同时也是将返回结果经过URL编码之后作为参数缀在跨域文件URL后面。
在跨域文件中,包含一段JavaScript代码,这段代码完成的功能,是从URL中提取结果参数,经过一定处理后调用原来的 http://example1.com/index.php页面中的一个预先约定好的callback函数,同时将结果参数传给这个函数。http: //example1.com/index.php页面和跨域文件是在同一个域下的,因此这个函数调用可以通过。跨域文件所在iframe和原来的 http://example1.com/index.php页面的关系,在前述第一种选择下,后者是前者的父窗口,在第二种选择下,后者是前者的父窗口的父窗口。
根据前面的叙述,有了跨域文件之后,我们就可以实现通过iframe方式在不同域之间进行JavaScript调用。这个调用过程可以完全跟 HTTP请求无关,例如有些站点可以支持动态地调整在页面中嵌入的第三方iframe的高度,这其实是通过在第三方iframe里面检测自己页面的高度变化,然后通过跨域方式的函数调用将这个变化告知父窗口来完成的。
既然利用iframe可以实现跨域JavaScript调用,那么跨域提交POST请求等其它类型的HTTP请求就不是难事。例如我们可以跨域调用目标域的JavaScript代码在目标域下提交Ajax请求(GET/POST/etc.),然后将返回的结果再跨域传原来的域。
使用iframe跨域,优点是功能强大,支持各种浏览器,几乎可以完成任何跨域想做的事情;缺点是实现复杂,要处理很多浏览器兼容问题,并且传输的数据不宜过大,过大了可能会超过浏览器对URL长度的限制,要考虑对数据进行分段传输等。
3. 利用flash实现跨域HTTP请求
据称,flash在浏览器中的普及率高达90%以上。
flash代码和JavaScript代码之间可以互相调用,并且flash的“安全沙箱”机制与JavaScript的安全机制并不尽相同,因此,我们可以利用flash来实现跨域提交HTTP请求(支持GET/POST等)。
例如,我们用浏览器访问http://example1.com/index.php这个页面,在这个页面中引用了http: //example2.com/flash.swf这个flash文件,然后在flash代码中向http://example3.com /webservice.php发送HTTP请求。
这个请求能否被成功发送,取决于在example3.com的根路径下是否放置了一个crossdomain.xml以及这个 crossdomain.xml的配置如何。flash的“安全沙箱”会保证:仅当example3.com服务器在根路径下确实放置了 crossdomain.xml文件并且在这个文件中配置了允许接受来自example2.com的flash的请求时,这个请求才能真正成功。下面是一个crossdomain.xml文件内容的例子:
- <? xml version = "1.0" ?>
- < cross-domain-policy >
- < allow-access-from domain = "example2.com" />
- </ cross-domain-policy >
<?xml version="1.0"?> <cross-domain-policy> <allow-access-from domain="example2.com" /> </cross-domain-policy>
4. window.postMessage
window.postMessage是HTML标准的下一个版本HTML5 支持的一个新特性。受当前互联网技术突飞猛进的影响,浏览器跨域通信的需求越来越强烈,HTML标准终于把跨域通信考虑进去了。但目前HTML5仍然只是一个draft。
window.postMessage是一个安全的实现直接跨域通信的方法。但是目前并不是所有浏览器都能支持,只有Firefox 3、Safari 4和IE8可以支持这个调用。
使用它向其它窗口发送消息的调用方式大概如下:
- otherWindow.postMessage(message, targetOrigin);
otherWindow.postMessage(message, targetOrigin);
在接收的窗口,需要设置一个事件处理函数来接收发过来的消息:
- window.addEventListener( "message" , receiveMessage, false );
- function receiveMessage(event){
- if (event.origin!== "http://example.org:8080" ) return ;}
window.addEventListener("message", receiveMessage, false); function receiveMessage(event){ if (event.origin!== "http://example.org:8080") return;}
消息包含三个属性:data、origin(携带发送窗口所在域的真实信息)和source(代表发送窗口的handle)。
安全性考虑:使用window.postMessage,必需要使用消息的origin和source属性来验证发送者的身份,否则会造成XSS漏洞。
window.postMessage在功能上同iframe实现的跨域功能同样强大,并且使用简单,效率更高,但缺点是它目前在浏览器兼容方面有待提高。
总结完所有的跨域方式之后,我们要时刻铭记,虽然跨域技术能给你带来更多的功能,催生出更灵活和更加平台化的产品,但是功能的放开也总是意味着安全的风险。在实现跨域技术的每个步骤和细节,都要时刻在头脑中考虑到对安全带来的影响,避免成为XSS攻击的漏洞。
发表评论
-
关于“Internet Explorer无法打开站点,已终止操作”的解决方法
2012-11-28 15:24 1653时间:2012-1-28 在做内蒙的项目时点击左侧菜单 ... -
javascript 闭包
2012-09-21 10:17 1044转载:http://www.ruanyifeng. ... -
关于javascript中apply()和call()方法的区别
2012-01-04 14:20 999转自:http://www.cnblogs.com/fight ... -
Javascript中call的使用 【转】
2012-01-04 13:40 926转自: http://hszy00232.b ... -
弹出层后有遮罩层【转载】
2011-11-27 10:07 2160转载:http://blog.163.com/wu_qihui ... -
让document的背景变红
2011-11-26 09:44 1108<!DOCTYPE html PUBLIC " ... -
判断元素是否为HTMLElement元素【转载】
2011-11-22 11:02 1200地址:http://www.cnblogs.com/snand ... -
点击右键弹出弹出层【转】
2011-10-19 18:00 1298原地址:http://js.alixixi.com/a/201 ... -
页面加载方法例子
2011-10-17 18:04 1255<script type="text/java ...
相关推荐
同源策略与 File 协议导致的跨域问题解决方案 同源策略是出于安全考虑而诞生的约定,规定了只能在本域内进行资源访问。所谓同源是指“协议+域名+端口”三者相同。不同源之间进行资源访问,就需要跨域。特殊地,有三...
1. **JSONP(JSON with Padding)**:JSONP是一种早期的跨域解决方案,它依赖于`<script>`标签不受同源策略限制的特点。通过动态创建`<script>`标签,设置其`src`属性为提供服务的服务器接口,并由服务器返回一个包裹...
本篇文章将详细介绍如何解决Geoserver的跨域问题。 首先,我们需要理解跨域问题的背景。根据同源策略,浏览器只允许与同一源(协议+域名+端口)的请求进行通信。但在实际应用中,比如一个网站前端和Geoserver不在同...
JavaScript跨域问题,是Web开发中常见的一个挑战,由于浏览器的同源策略限制,JavaScript无法直接访问不同源的资源,这在实现某些功能时会带来不便。本文将深入探讨JavaScript跨域问题的原因、影响以及多种解决方案...
面对这样的问题,我们可以采用以下几种跨域解决方案: 1. **CORS(Cross-Origin Resource Sharing)**:服务器可以通过设置响应头`Access-Control-Allow-Origin`来允许特定的源进行跨域请求。例如,服务器端可以在...
JSONP是一种较早的跨域解决方案,它利用了浏览器允许`<script>`标签跨域加载资源的特性。通过动态创建`<script>`标签,并指定其`src`属性为一个返回JSON数据的函数调用,服务器将数据包裹在函数调用中返回,客户端...
本文将深入探讨JavaScript跨域问题及其解决方案,以帮助开发者理解和应对这一问题。 首先,了解同源策略是解决问题的关键。同源策略是浏览器为了保障用户数据安全而实施的一种机制,它禁止了一个源的文档或脚本获取...
JSONP 是一种早期的跨域解决方案,适用于只支持GET请求的浏览器。SignalR 1.x 版本支持 JSONP,但在 SignalR 2.x 及更高版本中已被 CORS 替代。如果需要支持旧浏览器,需要确保 SignalR Hub 支持 JSONP 请求。 3. ...
JavaScript跨域和Ajax跨域是Web开发中常见的问题,尤其在进行前后端分离或API调用时,由于浏览器的同源策略限制,不同域名、协议或端口的资源请求会被阻止,这就是所谓的“跨域”。本文将深入探讨JavaScript和Ajax...
JQuery的跨域解决方案主要依赖于JSONP(JSON with Padding)技术。JSONP是一种绕过同源策略的方式,它利用HTML中的`<script>`标签没有同源策略限制的特点。当jQuery使用`dataType: 'jsonp'`时,它实际上是在做以下几...
在GIS(地理信息系统)开发中,ArcGIS JavaScript API(arcgis js)是Esri公司提供的一款...不过,需要注意的是,跨域问题的解决方案应根据项目需求和安全性考虑进行选择,确保既能满足功能需求,又能保障数据安全。
Nginx 跨域问题解决方案 Nginx 是一个流行的开源 Web 服务器软件,广泛应用于 Web 服务器管理。然而,在使用 Nginx 进行服务器管理时,经常会遇到跨域问题。跨域问题是指在不同的域名、端口或协议下,无法访问...
标题《JS跨域访问解决方案总结.pdf》指明文档的核心内容是关于JavaScript跨域访问问题的解决方法。跨域访问问题是指由于浏览器的同源策略限制,网页中JavaScript代码出于安全原因不能访问另一个源(域名、协议或端口...
解决方案: 1.jsonp 在远程服务器上设法动态的把数据装进js格式的文本代码段中,供客户端调用和进一步处理;在前台通过动态添加script标签及src属性,表面看上去与ajax极为相似,但是,这和ajax并没有任何关系;...
本资料包“Tomcat跨域请求资源解决方案.zip”显然是针对这个问题提供了一个具体的解决方案,主要聚焦于如何在Apache Tomcat服务器上配置以允许跨域请求。 Tomcat是Java Servlet容器,广泛用于部署Java Web应用程序...
为了解决跨域问题,PDF.js 提供了几种解决方案: 1. 服务器端配置:在服务器端设置 CORS 头部,允许来自其他域的请求。例如,在 Apache 或 Nginx 配置中添加 `Access-Control-Allow-Origin` 头,指定允许访问的源...
在没有服务器环境的情况下,这种方法可以实现AJAX读取本地文件,但是请注意,这种解决方案仅限于开发阶段,因为它依赖于浏览器的沙盒环境,且不适用于所有浏览器。在生产环境中,应该使用服务器来托管文件,并通过...
JSONP是一种早期的跨域解决方案,它是通过动态创建`<script>`标签来加载数据的。因为`<script>`标签不受同源策略限制,可以通过`src`属性指向提供JSON数据的外部服务。服务端返回的数据是一个JavaScript函数调用,...
JavaScript跨域访问解决方案 在Web开发中,由于浏览器的安全策略——同源策略(Same Origin Policy),不同源的脚本之间无法直接通信或访问彼此的资源。同源策略规定,只有当两个URL的协议、域名和端口都相同时,...