Ajax跨域访问问题-方法大全

时间:2022-09-03 12:20:09

Case I. Web代理的方式 (on Server A)

即用户访问A网站时所产生的对B网站的跨域访问请求均提交到A网站的指定页面,由该页面代替用户页面完成交互,从而返回合适的结果。此方案可以解决现阶段所能够想到的多数跨域访问问题,但要求A网站提供Web代理的支持,因此A网站与B网站之间必须是紧密协作的,且每次交互过程,A网站的服务器负担增加,且无法代用户保存session状态。

Case II. on-Demand方式 (on Server A)

MYMSN的门户就用的这种方式,不过 MYMSN中不涉及跨域访问问题。在页面内动态生成新的<script>,将其src属性指向别的网站的网址,这个网址返回的内容必须是合法的Javascript脚本,常用的是JSON消息。此方案存在的缺陷是, script的src属性完成该调用时采取的方式时get方式,如果请求时传递的字符串过大时,可能会无法正常运行。不过此方案非常适合聚合类门户使用。

<html>
<head>
<script>
function loadContent()
{
var s=document.createElement('SCRIPT');
s.src='http://www.anotherdomain.com/TestCrossJS.aspx?f=setDivContent';
document.body.appendChild(s);
}

function setDivContent(v)
{
var dv = document.getElementById("dv");
dv.innerHTML = v; 
}
</script>
</head>
<body>
<div></div>

<input value="Click Me">
</body>
</html>

其中的www.anotherdomain.com/TestCrossJS.aspx是这样的,

<script runat="server">
void Page_Load(object sender, EventArgs e)
{
  string f = Request.QueryString["f"];
  Response.Clear();
  Response.ContentType = "application/x-javascript";
  Response.Write(String.Format(@"
                   {0}('{1}');", 
                   f,
                   DateTime.Now));
  Response.End();
}
</script>

点击“Click Me”按钮,生成一个新的script tag,下载对应的 Javascript 脚本,结束时回调其中的setDivContent(),从而更新网页上一个div的内容。

Case III. iframe方式 (on Server A)

查看过醒来在javaeye上的一篇关于跨域访问的帖子,他提到自己已经用iframe的方式解决了跨域访问问题。数据提交跟获取,采用iframe这种方式的确可以了,但由于父窗口与子窗口之间不能交互(跨域访问的情况下,这种交互被拒绝),因此无法完成对父窗口效果的影响。

在页面内嵌或动态生成指向别的网站的IFRAME,然后这2个网页间可以通过改变对方的anchor hash fragment来传输消息。改变一个网页的anchor hash fragment并不会使浏览器重新装载网页,所以一个网页的状态得以保持,而网页本身则可以通过一个计时器(timer)来察觉自己anchor hash的变化,从而相应改变自己的状态。

1. http://domain1/TestCross.html:

<html>
<head>
<script>
var url = "http://domain2/TestCross.html"
var oldHash = null;
var timer = null;

function getHash() 
{
var hash = window.location.hash;
if ((hash.length >= 1) && (hash.charAt(0) == '#')) 
{
hash = hash.substring(1);
}

return hash;
}
function sendRequest()
{
var d = document;
var t = d.getElementById('request');
var f = d.getElementById('alienFrame');
f.src = url + "#" + t.value + "<br/>" + new Date();
}

function setDivHtml(v)
{
var d = document;
var dv = d.getElementById('response');
dv.innerHTML = v;
}

function idle()
{
var newHash = getHash();

if (newHash != oldHash)
{
setDivHtml(newHash);
oldHash = newHash;
}

timer = window.setTimeout(idle, 100);
}

function window.onload()
{
timer = window.setTimeout(idle, 100);
}
</script>
</head>
<body>

请求:<input> <input value="发送" /><br/>
回复:<div></div>

<iframe src="http://domain2/TestCross.html"></iframe>

</body>
</html>

2. http://domain2/TestCross.html:

<html>
<head>
<script>
var url = "http://domain1/TestCross.html"
var oldHash = null;
var timer = null;

function getHash() 
{
var hash = window.location.hash;
if ((hash.length >= 1) && (hash.charAt(0) == '#')) 
{
hash = hash.substring(1);
}

return hash;
}
function sendRequest()
{
var d = document;
var t = d.getElementById('request');
var f = parent;
//alert(f.document); //试着去掉这个注释,你会得到“Access is denied”
f.location.href = url + "#" + t.value + "<br/>" + new Date();
}

function setDivHtml(v)
{
var d = document;
var dv = d.getElementById('response');
dv.innerHTML = v;
}

function idle()
{
var newHash = getHash();

if (newHash != oldHash)
{
setDivHtml(newHash);
oldHash = newHash;
}

timer = window.setTimeout(idle, 100);
}

function window.onload()
{
timer = window.setTimeout(idle, 100);
}
</script>
</head>
<body>

请求:<input> <input value="发送" /><br/>
回复:<div></div>

</body>
</html>

两个网页基本相同,第一个网页内嵌一个IFRAME,在点击“发送”按钮后,会将文本框里的内容通过hash fragment传给IFRAME。点击IFRAME里的“发送”按钮后,它会将文本框里的内容通过hash fragment传给父窗口。因为是只改动了hash fragment,浏览器不会重新load网页内容,这里使用了一个计时器来检测URL变化,如果变化了,就更新其中一个div的内容 。

Case IV. 用户本地转储方式 (local)

IE本身依附于windows平台的特性为我们提供了一种基于iframe,利用内存来“绕行”的方案,即两个window之间可以在客户端通过windows剪贴板的方式进行数据传输,只需要在接受数据的一方设置Interval进行轮询,获得结果后清除Interval即可。FF的平*立性决定了它不支持剪贴板这种方式,而以往版本的FF中存在的插件漏洞又被fixed了,所以FF无法通过内存来完成暗渡陈仓。而由于文件操作FF 也没有提供支持(无法通过Cookie跨域完成数据传递),致使这种技巧性的方式只能在IE中使用。

Case V: (其实还是在服务端A用iframe解决了与服务器B通信的问题)

要解决的问题:发生在用户提交网页 URL (还包括 Tag, Notes 等)给 Bookmark 服务器时。

关于 URL 的提交至少可以有三种方式:

1.       登陆 Bookmark 服务器的提交页面,将要收藏的 URL 通过该页面提交给服务器。

2.       安装浏览器插件,通过插件将 URL 提交给服务器。

3.       从 Bookmark 服务器动态加载 javascript 小工具到当前页面,通过它来完成提交工作。

第一种方式开发起来最简单,但对用户来讲比较麻烦,每次都需要先登陆 Bookmark 服务器才能完成提交;第二种方式我并不熟悉插件开发,而且用户也不喜欢太多的插件堆满自己的浏览器;第三种方式开发难度小,又避免了每次登陆服务器的麻烦,所以最终采用它。第三种方式中动态加载的 javascript 小工具除了需要生成 UI 供用户填写信息( URL , tag , notes 等),当用户点击提交的时候,还要完成与服务器通信的功能。

跨域访问,简单来说就是 A 网站的 javascript 代码试图访问 B 网站,包括提交内容和获取内容。由于安全原因,跨域访问是被各大浏览器所默认禁止的。写过跨域访问 ajax 的朋友相信都遇到过被告知“没有权限”的情况。通过 XMLHttp 来发送数据给 Bookmark 服务器的尝试失败了。于是,看到网上的一些资料,我又开始尝试用 javascript 小工具在用户网页动态创建一个隐藏的 iframe, iframe 的 src 指向服务器的一个 servlet ,试图通过调用 iframe 中提供的 javascript 来完成与服务器的通信。但不幸的是,用户网页中的 javascript 代码访问 iframe 也被浏览器归为跨域访问(特指 iframe 的 src 指向其它网站的情形),尝试再次失败。

最终,在一篇文章中看到,与 iframe 不同,如果 A 网站从 B 网站加载 javascript , A 网站可以*的访问该 javascript 的内容,并不会被浏览器认为是跨域访问。模仿刚才 iframe 的思路,当用户点击提交时,可以动态创建一个 javascript 对象,该对象的 src 指向 Bookmark 服务器的一个 servlet ,注意: URL 、 Tag 、 Notes 、 User 、Password 等信息被作为 src URL 参数传给服务器。请看下面的代码:

var url = "http://localhost:8080/Deeryard/BookmarkServlet?" +

"url=" + url_source + "&" + "title=" + title + "&" +

"tag=" + tag + "&" + "notes=" + notes + "&" + "user=" + user + "&" + "password=" + password;

url = encodeURI(url);

//Submit to server with a trick

var js_obj = document.createElement( "script" );

js_obj.type = "text/javascript" ;

js_obj.setAttribute( "src" , url);

//Get response from server by appending it to document

document.body.appendChild(js_obj);

上面例子中, js_obj.setArrribute() 将信息作为 src 的 URL 参数提交给了 Bookmark servlet 。那么用户又如何取得服务器的响应信息呢?答案就是最末一行代码, servlet 的输出必须是 javascript 代码,它可以调用用户网页上的其他 javascript 函数,以及操作 dom 对象。下面的 servlet 代码生成了一个 javascript 函数调用:

out.write("onServerResponse(INADEQUATE_INFORMATION);");

document.body.appendChild(js_obj) 执行后 onServerResponse( INADEQUATE_INFORMATION) 就会得到执行,使客户网页响应服务器结果。这样一个完整的通信过程就完成了。

CaseVI:Tomcat + PHP + HTML(含JS)(on Server A)

服务器A上已经装好了Tomcat, 我们写一个test.html(含JS),再写一个PHP文件(由其来完成跨域通信要求)。

Ajax跨域访问问题-方法大全的更多相关文章

  1. 浅析JSONP-解决Ajax跨域访问问题

    浅析JSONP-解决Ajax跨域访问问题 很久没有写随笔了,总是感觉没时间,其实时间就是...废话少说,前几天,工作上有一新需求,需要前端web页面异步调用后台的Webservice方法返回信息.实现 ...

  2. Ajax跨域访问解决办法

    方法1. jsonp实现ajax跨域访问示例 jsp代码: <body> <input type="button" onclick="testJsonp ...

  3. Web Api 2&lpar;Cors&rpar;Ajax跨域访问

    支持Ajax跨域访问ASP.NET Web Api 2(Cors)的简单示例教程演示   随着深入使用ASP.NET Web Api,我们可能会在项目中考虑将前端的业务分得更细.比如前端项目使用Ang ...

  4. Hbuilder编辑App时,ajax跨域访问失败问题

    今天试着用Hbuilder写app的前段显示页面,在第一步时就被打住了,ajax异步调用服务器的登录接口时,报错, 显示这样的错误 XMLHttpRequest cannot loadhttp://w ...

  5. Ajax跨域访问等问题

    前端时间公司接口整顿,所有接口放一起了,然后我就写了一大堆API接口....... 今天用上了,公用人员库,前台通过ajax访问, 先是以‘json’作为数据格式进行访问,直接response fie ...

  6. ajax跨域访问的解决方案

    今天的工作中要访问摄像机内部的一个web站点,这就涉及到jquery的ajax跨域访问的问题.我使用的是jquery1.7的版本,下面总结如下: 问题一:一开始用IE调试,总是返回No Transpo ...

  7. ajax 跨域访问的解决方案

    ajax 跨域访问的解决方案 一.什么是跨域: 1.什么样的请求属于跨域: 域名,端口有任何一个不相同都属于跨域: 二.跨域的常用几种解决方案: 1.jsonp: 2.iframe: 3.webcon ...

  8. 关于JQuery Ajax 跨域 访问&period;net WebService

    关于这个 jQuery Ajax跨域访问 WebService 前天整了好几个小时没整明白 今天再看一下 结果突然就顿悟了 1.建一个空webApplication --添加--新建项--web服务( ...

  9. JS Ajax跨域访问

    js ajax跨域访问报"No 'Access-Control-Allow-Origin' header is present on the requested resource 如果请求的 ...

随机推荐

  1. 篇三:访问JSON静态文件

    背景:在定位的时候带出车牌号的前两位,这里就有一个地址和车牌号前两位的映射关系,这个映射关系起初是通过Ajax在页面加载的时候请求去数据库里面查出来赋给一个变量,然后去操作,但是这个过程通常需要4~7 ...

  2. 从hadoop框架与MapReduce模式中谈海量数据处理

    http://blog.csdn.net/wind19/article/details/7716326 前言 几周前,当我最初听到,以致后来初次接触Hadoop与MapReduce这两个东西,我便稍显 ...

  3. DELL配置信息

    CPU详情CPU厂商 英特尔CPU (英特尔)Intel(R) Core(TM) i3 CPU M 370 @ 2.40GHzCPU核心数 2CPU默认频率 2400 MhzCPU外频 533 MHz ...

  4. 当x含有偶数个1,返回1,否则为0。

    题目描述: /* Return 1 when x contains an even number of 1s;0 otherwise. Assume W=32 */ int even_ones(uns ...

  5. LeetCode &amp&semi; Q88-Merge Sorted Array-Easy

    Array Two Pointers Description: Given two sorted integer arrays nums1 and nums2, merge nums2 into nu ...

  6. ionic4&plus;angular6 混合移动开发 capacitor cordova

    首先要更新或者安装 ionic cli npm install -g ionic 创建项目 ionic start ionic-angular tabs --type=angular –type=an ...

  7. &lbrack;转帖&rsqb;前端-chromeF12 谷歌开发者工具详解 Console篇

    前端-chromeF12 谷歌开发者工具详解 Console篇 https://blog.csdn.net/qq_39892932/article/details/82655866 趁着搞 cloud ...

  8. OpenRefine

    无论是现今的大数据还是企业内部的小数据,都存在一些普遍的问题,如数据格式不对需要转换,一个单元格内包含多个含义的内容,包含重复项等等,虽然我们也可以使用excel解决,但是excel天生有诸多限制,比 ...

  9. &lbrack;luogu1962&rsqb;斐波那契数列

    来提供两个正确的做法: 斐波那契数列双倍项的做法(附加证明) 矩阵快速幂 一.双倍项做法 在偶然之中,在百度中翻到了有关于斐波那契数列的词条(传送门),那么我们可以发现一个这个规律$ \frac{F_ ...

  10. Java编程从头开始---老妪能解

    思想导向: 今天想要分享的是最基础的东西就是如何写一个简单的代码,很多人都是小白,需要的其实并不是很高端的理论,框架和思维模式啊,设计方法啊,这些对于一个新人来说实在是好高骛远,说的那么高端,结果要学 ...