手机
当前位置:查字典教程网 >编程开发 >Javascript教程 >JS跨域总结
JS跨域总结
摘要:javascript跨域有两种情况:1、基于同一父域的子域之间,如:a.c.com和b.c.com2、基于不同的父域之间,如:www.a.c...

javascript跨域有两种情况:

1、基于同一父域的子域之间,如:a.c.com和b.c.com

2、基于不同的父域之间,如:www.a.com和www.b.com

3、端口的不同,如:www.a.com:8080和www.a.com:8088

4、协议不同,如:http://www.a.com和https://www.a.com

对于情况3和4,需要通过后台proxy来解决,具体方式如下:

a、在发起方的域下创建proxy程序

b、发起方的js调用本域下的proxy程序

c、proxy将请求发送给接收方并获取相应数据

d、proxy将获得的数据返回给发起方的js

发起方页面代码如下:

复制代码 代码如下:

<form id="form1" runat="server">

<div>

<input type="text" id="txtSrc" value="http://www.gzsums.edu.cn/webclass/html/html_design.html" />

<input id="btnProxy" type="button" value="通过Proxy获取数据" /><br />

<br />

<br />

</div>

<div id="divData"></div>

</form>

</body>

<script language="javascript" type="text/javascript">

function GetDataFromProxy() {

var src = document.getElementById('txtSrc').value;

var request = null;

if (window.XMLHttpRequest) {

request = new XMLHttpRequest();

}

else if (window.ActiveXObject) {

request = new ActiveXObject("Microsoft.XMLHTTP");

}

request.onreadystatechange = function() {

var ready = request.readyState;

var data = null;

{

if (ready == 4) {

data = request.responseText;

document.getElementById('divData').innerHTML = data;

}

else {

document.getElementById('divData').text = "Loading";

}

}

}

var url = "Proxy.ashx?src=" + escape(src);

request.open("get",url,false);

request.send(null);

}

</script>

发起方Proxy代码如下:

复制代码 代码如下:

using System.Data;

using System.Linq;

using System.Web;

using System.Web.Services;

using System.Web.Services.Protocols;

using System.Xml.Linq;

using System.IO;

using System.Net;

using System.Text;

namespace WebApplication1

{

/// <summary>

/// Summary description for $codebehindclassname$

/// </summary>

[WebService(Namespace = "http://tempuri.org/")]

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

public class Proxy : IHttpHandler

{

const int BUFFER_SIZE = 8 * 1024;

public void ProcessRequest(HttpContext context)

{

context.Response.ContentType = "text/plain";

string src = context.Request["src"];

WebRequest wr = WebRequest.Create(src);

WebResponse wres = wr.GetResponse();

Encoding resEncoding = System.Text.Encoding.GetEncoding("gb2312");

StreamReader sr = new StreamReader(wres.GetResponseStream(), resEncoding);

string html = sr.ReadToEnd();

sr.Close();

wres.Close();

context.Response.Write("<br/><br/><br/><br/>");

context.Response.Write(html);

}

public bool IsReusable

{

get

{

return false;

}

}

}

}

而情况1和2除了通过后台proxy这种方式外,还可以有7种办法来解决:

1、document.domain+iframe(只能解决情况1):

a、在发起方页面和接收方页面设置document.domain,并将值设为父域的主域名(window.location.hostname)

b、在发起方页面创建一个隐藏的iframe,iframe的源是接收方页面

c、根据浏览器的不同,通过iframe.contentDocument || iframe.contentWindow.document来获得接收方页面的内容

d、通过获得的接收方页面的内容来与接收方进行交互

这种方法有个缺点,就是当一个域被攻击时,另一个域会有安全漏洞出现。

发起方页面代码如下:

复制代码 代码如下:

<body>

<div>

<input type="text" id="txtSrc" value="http://b.a.com/DomainTest2.htm" />

<input id="btnDomain" type="button" value="通过Domain获取数据" /><br />

<br />

<br />

</div>

<div id="divData"></div>

</body>

<script language="javascript" type="text/javascript">

document.domain = 'a.com';

var src = document.getElementById('txtSrc').value;

var ifr = document.createElement('iframe');

ifr.src = src;

ifr.style.display = 'none';

document.body.appendChild(ifr);

function GetDataFromDomain() {

var doc = ifr.contentDocument || ifr.contentWindow.document;

alert(doc.getElementById("data").value);

}

</script>

接收方页面代码如下:

复制代码 代码如下:

<body>

<input type="hidden" id="data" value="Cross Domain" />

</body>

<script language="javascript" type="text/javascript">

document.domain = 'a.com';

</script>

2、动态创建script:

a、在发起方页面动态加载一个script,script的URL指向接收方的一个处理地址(后台),该地址返回的javascript方法会被执行,另外URL中可以传入一些参数,该方法只支持GET方式提交参数。

b、加载的script可以在调用跨域js方法后再做一些自己的处理

发起方页面的代码如下:

复制代码 代码如下:

<head>

<title>Script Test</title>

<script language="javascript" type="text/javascript">

function load_script(callback){

var head = document.getElementsByTagName('head')[0];

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

var src = document.getElementById('txtSrc').value;

script.type = 'text/javascript';

script.src = src;

//借鉴了jQuery的script跨域方法

script.onload = script.onreadystatechange = function(){

if((!this.readyState||this.readyState === "loaded"||this.readyState === "complete")){

callback && callback();

// Handle memory leak in IE

script.onload = script.onreadystatechange = null;

if ( head && script.parentNode ) {

head.removeChild( script );

}

}

};

// Use insertBefore instead of appendChild to circumvent an IE6 bug.

head.insertBefore( script, head.firstChild );

}

</script>

</head>

<body>

<input type="text" id="txtSrc" value="http://www.b.com/scripttest.aspx" />

<input type="button" value="通过动态创建script标签来获取数据"/>

</body>

接收方服务器端代码如下:

复制代码 代码如下:

protected void Page_Load(object sender, EventArgs e)

{

Response.Clear();

Response.ContentType = "application/x-javascript";

Response.Write(String.Format(@"alert('{0}');", DateTime.Now));

Response.End();

}

3、location.hash+iframe:

a、发起方创建一个隐藏的iframe,iframe的源指向接收方的页面,并通过接收方页面的hash值来传送数据

b、发起方创建一个定时器,定时检查自己的location.hash并作相应的处理

c、接收方创建一个隐藏的iframe,iframe的源指向发起方所在域的一个代理页面,并将接收方根据发起方传入的数据而处理后的数据通过代理页面的hash值来传送

d、接收方创建一个定时器,定时检查自己的location.hash并作相应的处理

e、代理页面创建一个定时器,定时检查自己的location.hash并同步更新发起方页面的hash值

www.a.com/a.html#aaa,其中#aaa就是location.hash值

发起方页面代码如下:

复制代码 代码如下:

<body>

<div>

<input type="text" id="txtSrc" value="1" />

<input id="btnAddHash" type="button" value="添加Hash值" />

<iframe id="ifr1"></iframe>

</div>

</body>

<script language="javascript" type="text/javascript">

function addHash() {

var src = document.getElementById('txtSrc').value;

if (src.length > 0) {

changeHash(src);

}

}

function changeHash(src) {

if (document.getElementById('ifr1')) {

var ifr = document.getElementById('ifr1');

ifr.src = 'http://www.b.com/Test/HashTest2.htm#' + src;

}

else {

var ifr = document.createElement('iframe');

ifr.setAttribute('id', 'ifr1');

ifr.src = 'http://www.b.com/Test/HashTest2.htm#' + src;

ifr.style.display = 'none';

document.body.appendChild(ifr);

}

}

function checkHash() {

if (location.hash && location.hash.length > 1) {

changeHash(location.hash.substring(1));

}

}

setInterval(checkHash, 2000);

</script>

接收方页面代码如下:

复制代码 代码如下:

<body>

<iframe id="ifr2"></iframe>

</body>

<script language="javascript" type="text/javascript">

function checkHash() {

if (location.hash && location.hash.length > 1) {

var hashData = location.hash.substring(1);

var ifr = null;

if (document.getElementById('ifr2')) {

ifr = document.getElementById('ifr2');

}

else {

ifr = document.createElement('iframe');

ifr.setAttribute('id', 'ifr2');

ifr.style.display = 'none';

document.body.appendChild(ifr);

}

switch (hashData) {

case '1':

alert('One');

if (ifr) {

ifr.src = 'http://www.a.com/test/HashTest3.htm#2';

}

break;

case '2':

alert('Two');

if (ifr) {

ifr.src = 'http://www.a.com/test/HashTest3.htm#1';

}

break;

default:

break;

}

}

}

setInterval(checkHash, 2000);

</script>

发起方域下的代理页面代码如下:

复制代码 代码如下:

<body></body>

<script language="javascript" type="text/javascript">

function checkHash() {

if (parent && parent.parent && parent.parent.location && self.location.hash.length > 1) {

parent.parent.location.hash = self.location.hash.substring(1);

}

}

setInterval(checkHash, 500);

</script>

4、window.name:

a、发起方页面创建一个隐藏的iframe,并且源指向接收方页面

b、接收方在自己页面通过script将需要传送的数据放入window.name里

c、发起方在iframe的onload方法里将iframe的源改为和自己在同一个域下的代理页面(因为只能是同一个域下才能访问window.name的值)

d、获取window.name的值(虽然iframe的源改变了,但是window.name的值不会变)

window.name的值差不多可以有2MB大小

发起方页面代码如下:

复制代码 代码如下:

<body>

<div>

<input id="btnName" type="button" value="通过window.name获取数据" />

<iframe id="ifr1" src="http://www.b.com/Test/NameTest2.htm"></iframe>

</div>

</body>

<script language="javascript" type="text/javascript">

var ischanged = false;

function changeSrc() {

if (document.getElementById('ifr1')) {

var ifr = document.getElementById('ifr1');

if (!ischanged) {

ischanged = true;

ifr.contentWindow.location = 'http://www.a.com/Test/NameTest3.htm';

}

else {

var data = ifr.contentWindow.name;

alert(data);

}

}

else {

var ifr = document.createElement('iframe');

ifr.setAttribute('id', 'ifr1');

ifr.src = 'http://www.b.com/Test/NameTest2.htm';

ifr.style.display = 'none';

document.body.appendChild(ifr);

}

}

function getData() {

setInterval(changeSrc, 2000);

}

</script>

接收方页面代码如下:

复制代码 代码如下:

<body></body>

<script language="javascript" type="text/javascript">

window.name = 'NameTest2';

</script>

发起方域下的代理页面代码如下:

<body></body>

(其实什么都不用写)

5、HTML5的postMessage

a、receiverWindow.postMessage(msg, targetOrigin),receiverWindow就是对接收消息的window的引用,可以是iframe的contentWindow/window.open的返回值/window.frames中的一个;msg就是要发送的消息,string类型;targetOrigin用于限制receiverWindow的URI,包括主域名和端口,使用“*”表示无限制,但是为了安全起见还是需要设置下,以防把消息发送给恶意的网站,如果targetOrigin的URI和receiverWindow的不符,则放弃发送消息。

b、接收方通过message事件来获得消息,并且通过event.origin的属性来验证发送方并通过event.data来获得传送的消息内容,event.source来获得发送方的window对象

发起方页面代码如下:

复制代码 代码如下:

<body>

<div>

<input id="btnPostMessage" type="button" value="通过PostMessage获取数据" />

<iframe id="ifr" src="http://www.b.com/Test/PostMessageTest2.htm"></iframe>

</div>

</body>

<script language="javascript" type="text/javascript">

function getData() {

var ifr = document.getElementById('ifr');

var targetOrigin = 'http://www.b.com';

if (ifr.contentWindow.postMessage) {

ifr.contentWindow.postMessage('PostMessageTest2', targetOrigin);

}

}

</script>

接收方页面代码如下:

复制代码 代码如下:

<body></body>

<script language="javascript" type="text/javascript">

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

if (event.origin == 'http://www.a.com') {

alert(event.data);

alert(event.source);

}

}, false);

</script>

6、window.opener(适用于IE6、7,也就是operner hack方法,不过貌似现在已经不管用了,只要打过微软的安全补丁.kb2497640就不能用了)

a、发起方页面创建一个隐藏的iframe,并且源指向接收方页面

b、发起方页面通过iframe.contentWindow.opener = {a: function(params){...}, b: function(params){...} ...}来定义可被接收方调用的方法

c、接收方页面通过window.opener.a/window.opener.b来调用发起方定义的方法

d、接收方页面通过parent.opener = {c: function(params){...}, d: function(params){...} ...}来定义可被发起方调用的方法

e、发起方页面通过opener.c/opener.d来调用接收方定义的方法

其实原理就是重置opener对象

发起方页面代码如下:

复制代码 代码如下:

<body>

<iframe id="ifr" src="http://www.b.com/test/OpenerTest2.htm"></iframe>

</body>

<script language="javascript" type="text/javascript">

var ifr = document.getElementById('ifr');

ifr.contentWindow.opener = { a: function(msg) { alert('我调用了a方法获得了消息:' + msg); } }

</script>

接收方页面代码如下:

复制代码 代码如下:

<body>

</body>

<script language="javascript" type="text/javascript">

window.opener.a('aaa');

</script>

7、window.navigator(适用于IE6、7,貌似现在还能用,还没被补丁掉)

a、发起方页面创建一个隐藏的iframe,并且源指向接收方页面

b、发起方页面通过window.navigator.a = function(params){...}; window.navigator.b = function(params){...}; 来定义被接收方调用的方法

c、接收方页面通过window.navigator.a(params); window.navigator.b(params);来调用发起方定义的方法

d、接收方页面通过window.navigator.c = function(params){...}; window.navigator.d = function(params){...}; 来定义被发起方调用的方法

e、发起方页面通过window.navigator.c(params); window.navigator.d(params);来调用接收方定义的方法

发起方页面代码如下:

复制代码 代码如下:

<body>

<iframe id="ifr" src="http://www.b.com/test/NavigatorTest2.htm"></iframe>

</body>

<script language="javascript" type="text/javascript">

window.navigator.a = function(msg) { alert('我调用了a方法获得了消息:' + msg); }

window.navigator.b = function(msg) { alert('我调用了b方法获得了消息:' + msg); }

setInterval(function() { window.navigator.c('ccc'); }, 2000);

setInterval(function() { window.navigator.d('ddd'); }, 2000);

</script>

接收方页面代码如下:

复制代码 代码如下:

<body>

</body>

<script language="javascript" type="text/javascript">

window.navigator.c = function(msg) { alert('我调用了c方法获得了消息:' + msg); }

window.navigator.d = function(msg) { alert('我调用了d方法获得了消息:' + msg); }

setInterval(function() { window.navigator.a('aaa'); }, 2000);

setInterval(function() { window.navigator.b('bbb'); }, 2000);

</script>

【JS跨域总结】相关文章:

Jquery使用css方法改变样式实例

破解Session cookie的方法

JavaScript基本数据结构

如何遍历对象的属性?

总结一些js自定义的函数

去除链接虚线全面分析总结

jQuery实现仿腾讯微博滑出效果报告每日天气的方法

js跨域请求的5中解决方式

JavaScript事件委托实例分析

JS实现跳转代码:多域名指向同一空间

精品推荐
分类导航