zoukankan      html  css  js  c++  java
  • AJAX跨域调用相关知识-CORS和JSONP(引)

    AJAX跨域调用相关知识-CORS和JSONP

    1、什么是跨域

    跨域问题产生的原因,是由于浏览器的安全机制,JS只能访问与所在页面同一个域(相同协议、域名、端口)的内容。

    但是我们项目开发过程中,经常会遇到在一个页面的JS代码中,需要通过AJAX去访问另一个服务器并返回数据,这时候就会受到浏览器跨域的安全限制了。


    这里要注意,如果只是通过AJAX向另一个服务器发送请求而不要求数据返回,是不受跨域限制的。浏览器只是限制不能访问另一个域的数据,即不能访问返回的数据,并不限制发送请求。

    我们接下来就为大家讲解最常见的跨域AJAX调用的解决方案,首先我们先准备一个测试环境:

    一个可以正常启动的Tomcat,默认端口8080;
    下载示例代码包ajax-cors-jsonp.zip,解压到Tomcat的webapps下,示例代码包中有test-client和test-service两个文件夹,分别包含我们示例的客户端和服务端代码;
    模拟一个多域环境,修改“C:WindowsSystem32driversetchosts”(如果文件不能编辑保存,需要在文件属性中去掉只读),在文件内容后面追加:
    127.0.0.1       www.aaa.com
    127.0.0.1       www.bbb.com

    启动Tomcat后,在浏览器中,分别测试

    http://www.aaa.com:8080/test-client/index.html

    http://www.bbb.com:8080/test-client/index.html

    两个页面是相同的,只是地址不同,都是在点击按钮后通过AJAX去访问http://www.bbb.com:8080/test-service/add.jsp。但是从www.aaa.com:8080访问时就返回了error,即浏览器不允许在www.aaa.com:8080的页面中通过AJAX获取来自www.bbb.com:8080服务器的返回数据。

    大家观察一下Tomcat控制台,会发现从www.aaa.com:8080访问时,虽然返回了错误,但服务端代码其实还是执行了。这个现象验证了跨域是可以发请求的,但是浏览器出于安全的原因不让我们在JS中获取返回数据。

    测试案例很简单,就是传入a=15&b=10两个参数,返回两个数据的和25,代码参见:

    test-client/index.html

    test-service/add.jsp

    2、CORS方案

    本节介绍的CORS(Cross-Origin Resource Sharing)方案是W3C在2014年正式推出的跨域访问方案,是真正的官方解决方案。这个方案的实现非常简单,只需要在服务端返回的头部信息中标明是否允许跨域访问,以及允许哪些域访问即可。

    接下来我们访问

    http://www.aaa.com:8080/test-client/index_cors.html

    成功了!!!我们来看代码中有什么改变?

    index_cors.html与index.html的差异仅是ajax调用的地址从add.jsp换成了add_cors.jsp,我们再来看add.jsp和add_cors.jsp的区别,会发现只增加了一行代码:

    response.setHeader(“Access-Control-Allow-Origin”, “http://www.aaa.com:8080″);

    如果不限定跨域访问的地址,可以把域名部分设置为*:

    response.setHeader(“Access-Control-Allow-Origin”, “*”);

    小结:

    CORS方案实现非常简单,只要服务在头部标明允许跨域访问即可。但是这个方案由于推出时间较晚,所以IE9及以下浏览器并没有支持这个机制。

    IE9及以下浏览器在安全设置里控制是否允许跨域数据访问:

    默认是上面的选项是禁用的,需要手动启用。同时,由于jQuery自动判断并认为当前浏览器不支持跨域,所以我们还需要用一行代码让jquery支持跨域ajax:

    $.support.cors = true;

    3、JSONP方案

    JSONP并不是一个官方协议,其本质上是一种巧妙的跨域获取JSON数据的编程技巧。

    我们首先来看实现,JSONP在实现上要比CORS稍微麻烦一点点,前后端要有点配合。

    首先运行http://www.aaa.com:8080/test-client/index_jsonp.html,这个页面里面AJAX后端请求换成了add_jsonp.jsp。

    接下来我们先解析代码:

    index_jsonp.html中,我们在$.ajax的参数上有点变化:

    type改成了get,JSONP只支持get请求,这个参数在JSONP场景下其实是可以忽略的,即使改成post,也会依然按get模式;
    dataType改成了jsonp,这个参数标明要采用JSONP方式进行调用;
    jsonp: “x5callback”,这个参数其实是一个约定的参数名,用于后端按照这个参数名获取一个回调函数名;
    jsonpCallback:这个参数用来指定上面那个参数对应的回调函数名,如果不指定,jQuery会自动生成一个随机的函数名。
    add_jsonp.jsp中,我们在最后数据返回部分做了一点处理:

    首先我们按照约定的参数名,获取回调函数名;
    String callbackName = request.getParameter(“x5callback”);
    返回的内容格式也不再仅是一个JSON数据,而是一个JS的函数调用形式:回调函数名(JSON数据)
    String jsonpResult = String.format(“%s(%s)”, callbackName, jsonResult);
    前后端需要做的工作就是这么多,但是这时候初学者一定觉得有点迷惑了,这个回调函数名到底是干什么用的?我们并没有定义什么回调函数啊?它是怎么工作的呢?

    我们简单的加一个调试很快就可以解开这个疑惑,在add_jsonp.jsp最终返回的数据中加一个debugger:

    String jsonpResult = String.format(“debugger;%s(%s)”, callbackName, jsonResult);

    接下来我们F12启动浏览器开发者工具,点击按钮后就会进入JS调试。

    这时候我们看到返回的是一个JS函数的调用,函数名是随机的,函数的参数就是那个我们构造的JSON。接下来,我们在控制台输入window.函数名,会发现这个函数是真实存在的!!!

    这是怎么回事呢???原来jQuery所谓的JSONP模式,其实是动态创建了一个<script>标签,标签的src属性指向一个URL(http://www.bbb.com:8080/test-service/add_jsonp.jsp?x5callback=jQuery18203749695811420679_1439276096319&a=15&b=10&_=1439276101932),这个URL里面除了包含我们的a和b两个参数,还包含一个x5callback参数,参数的值就是那个随机的函数名。这个script标签动态插入到当前页面后,自然就会将我们返回的内容当做JS加载到当前页面(这里我们返回的是JS,浏览器是不阻止的哦,页面可以从任何域加载JS脚本):

    debugger;jQuery18203749695811420679_1439276096319({“sum”: 25})

    加载后,按照JS的特性,这些代码会立即执行。而jQuery在这个之前已经动态创建了一个以随机函数名为名称的全局函数,用于接收返回数据,再往后jQuery通过一系列的逻辑代码最终把返回值给到了我们的success回调函数中。

    有关jQuery动态创建<script>相关的逻辑,大家可以在我们案例自带的jquery-1.8.2.js的8270行加上断点进行跟踪。

    小结:

    JSONP是以动态创建script标签为基础的一种编程技巧,来实现跨域获取JSON数据。

    支持目前所有浏览器,只是在实现方式上需要前后端代码有一点约定配合。

    但是,要注意由于JSONP是以script标签的src属性加载的,因此参数会收到URL长度的限制,只能适用于传入参数内容不多的场景。

    4、总结

    CORS方案实现简单,同时支持GET和POST请求,但是不支持IE9及以下浏览器。这时看官要问了,这么多浏览器不支持,这技术怎么用啊?手机啊!目前市面上所有的手机浏览器是全部支持CORS的,如果是为手机提供跨域服务CORS就够了。

    JSONP方案实现需要前后端配合,支持GET请求,支持所有浏览器,只是传入的参数内容受限于URL长度限制。

    引自:http://wex5.com/cn/ajax-cors-jsonp/

    下载资源:ajax-cors-jsonp.zip

  • 相关阅读:
    解析大型.NET ERP系统 权限模块设计与实现
    Enterprise Solution 开源项目资源汇总 Visual Studio Online 源代码托管 企业管理软件开发框架
    解析大型.NET ERP系统 单据编码功能实现
    解析大型.NET ERP系统 单据标准(新增,修改,删除,复制,打印)功能程序设计
    Windows 10 部署Enterprise Solution 5.5
    解析大型.NET ERP系统 设计异常处理模块
    解析大型.NET ERP系统 业务逻辑设计与实现
    解析大型.NET ERP系统 多国语言实现
    Enterprise Solution 管理软件开发框架流程实战
    解析大型.NET ERP系统 数据审计功能
  • 原文地址:https://www.cnblogs.com/wangweixznu/p/4761104.html
Copyright © 2011-2022 走看看