标签:jquery jsonp 跨域访问 cross domain mvc
随着产品的不断完善,应用需要部署到不同的服务器上,突然执行某一次请求的时候,浏览器不响应了,才意识到我们也需要跨域访问了。
上网搜索“crossdomain”能找到一大堆东西,可以水准大都很烂,东拼西凑,不知所云。有关跨域访问从原理到应用,写得最好的一篇文章是《Cross-domain communications with JSONP, Part 1: Combine JSONP andjQuery to quickly build powerful mashups》,花点时间读完它,就没什么疑惑了。
搬砖头翻译的事情不想干了,梳理几个我觉得重要的地方。
由于浏览器的自身策略,异步请求与页面来源不同域的站点,会引发安全性错误。 一般有三种方法突破这种限制:访问页面所在的站点进行代理;利用IFrame访问不同域的站点;剩下的就是现在主流JSONP(JSON with Padding)。
JSONP绝对是个坑爹的名字,其本质就是利用了动态插入JavaScript的原理(DynamicJavaScript Insertion)。浏览器虽然阻止跨域的异步请求,但是在HTML Header中的<script>和<link>标签可以引用任何来源的文件,我们可以动态创建一个<script>的标签,将它的src设定为异步请求的服务器地址,这样就能跨域请求了。但是这种模式下,浏览器接管了该请求,并处理响应结果。对于浏览器而言,只是通过GET方法试图下载被请求地址的内容,并且认为这是一个js文件,使用JavaScript引擎去执行其中的代码。所以如果要获取响应的结果,那么就要在下载内容中动脑筋,首先响应结果应该被封装成为JSON形式,同时请求发起者还需要提供一个回调函数,供下载完毕后,以响应结果作为参数执行该回调函数。
结合整个过程,我对JSONP是这样理解的:使用JSON填充响应结果。jQuery中的ajax方法对JSONP有很好的支持,甚至无需特别声明,jQuery内部根据请求地址自动判断,如果是跨域的就启动JSONP,如果是本域就是常规的AJAX。但是正因为跨域请求的返回结果不是常规的JSON,所以不仅需要客户端有特殊的方法,服务端也需要对JSONP进行专门的支持:服务端需要知道下载完毕后的回调函数是什么,需要把执行回调函数的JavaScript语句写入到响应流中。
这种专门支持JSONP的服务端被称之为“JSONP Service”,网上能搜索的绝大多数文档,都是谈客户端该怎么调用,没有涉及服务端,所以费了好大的劲才找到门路。
下面用一个简单的例子展示跨域请求的过程。
服务端(ASP.NET MVC 3.0)
[HttpGet] public ActionResult UserPath(Guid id,String callback) { String userPath = CreateUserDir(id); String output = String.Format("{0}(\"{1}\");", callback, userPath); this.Response.Write(output); return new HttpStatusCodeResult(200); }
首先服务端应该支持HTTPGET方法访问,回调函数应该作为请求的参数之一(如上述示例中的callback),响应流就是符合JavaScript语法规范的字符串,其中必须包含对于回调函数的调用语句。这里的响应结果比较简单,就是一个字符串。
客户端(jQuery 1.9)
var url = "http://server2/Pronunciation/UserPath?id=" + studentID + "&callback=?"; $.getJSON(url, null, function (result) { runtime.AddRecordRootPath(result); });
客户端可以用jQuery提供的任何AJAX相关的函数,getJSON足够简单,所以推荐一下。示例当中使用了一个匿名函数作为回调函数,所以“callback=?”,如果回调是一个定义好的函数,那么应该为“callback=<functionname>”。
方法有点绕,如果理解原理的,也很简单。
标签:jquery jsonp 跨域访问 cross domain mvc
原文地址:http://blog.csdn.net/mittermeyer/article/details/41484843