ajax 跨域问题(两种解决办法)

为什么会出现跨域

  • 跨域问题来源于JavaScript的同源策略,即只有 协议+主机名+端口号 (如存在)相同,则允许相互访问。也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源。跨域问题是针对JS和ajax的,html本身没有跨域问题,比如a标签、script标签、甚至form标签(可以直接跨域发送数据并接收数据)等
  • jsopn原理

    在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。

    比如,有个a.html页面,它里面的代码需要利用ajax获取一个不同域上的json数据,假设这个json数据地址是http://example.com/data.php,那么a.html中的代码就可以这样:

    QQ截图20130613230631

    我们看到获取数据的地址后面还有一个callback参数,按惯例是用这个参数名,但是你用其他的也一样。当然如果获取数据的jsonp地址页面不是你自己能控制的,就得按照提供数据的那一方的规定格式来操作了。

    因为是当做一个js文件来引入的,所以http://example.com/data.php返回的必须是一个能执行的js文件,所以这个页面的php代码可能是这样的:

    QQ截图20130613230631

    最终那个页面输出的结果是:

    QQ截图20130613230631

    所以通过http://example.com/data.php?callback=dosomething得到的js文件,就是我们之前定义的dosomething函数,并且它的参数就是我们需要的json数据,这样我们就跨域获得了我们需要的数据。

    这样jsonp的原理就很清楚了,通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。

    知道jsonp跨域的原理后我们就可以用js动态生成script标签来进行跨域操作了,而不用特意的手动的书写那些script标签。如果你的页面使用jquery,那么通过它封装的方法就能很方便的来进行jsonp操作了。

    QQ截图20130613230631

    原理是一样的,只不过我们不需要手动的插入script标签以及定义回掉函数。jquery会自动生成一个全局函数来替换callback=?中的问号,之后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的作用。$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数

  • CORS原理

  • CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
    第一种现象:No 'Access-Control-Allow-Origin' header is present on the requested resource,并且The response had HTTP status code 404
    出现这种情况的原因如下:
    本次ajax请求是“非简单请求”,所以请求前会发送一次预检请求(OPTIONS)
    服务器端后台接口没有允许OPTIONS请求,导致无法找到对应接口地址
    解决方案: 后端允许options请求
    第二种现象:No 'Access-Control-Allow-Origin' header is present on the requested resource,并且The response had HTTP status code 405
    这种现象和第一种有区别,这种情况下,后台方法允许OPTIONS请求,但是一些配置文件中(如安全配置),阻止了OPTIONS请求,才会导致这个现象
    解决方案: 后端关闭对应的安全配置
    第三种现象:No 'Access-Control-Allow-Origin' header is present on the requested resource,并且status 200
    比如origin头部检查不匹配,比如少了一些头部的支持(如常见的X-Requested-With头部),然后服务端就会将response返回给前端,前端检测到这个后就触发XHR.onerror,导致前端控制台报错
    解决方案: 后端增加对应的头部支持
    第四种现象:heade contains multiple values '*,*'
    表现现象是,后台响应的http头部信息有两个Access-Control-Allow-Origin:*
    解决方案:
    建议删除代码中手动添加的*,只用项目配置中的即可
    建议删除IIS下的配置*,只用项目配置中的即可
    解决ajax跨域
    一般ajax跨域解决就是通过JSONP解决或者CORS解决,如以下:
    CORS解决跨域问题
    CORS的原理上文中已经介绍了,这里主要介绍的是,实际项目中,后端应该如何配置以解决问题(因为大量项目实践都是由后端进行解决的),这里整理了一些常见的后端解决方案:
    PHP后台配置
    PHP后台得配置几乎是所有后台中最为简单的,遵循如下步骤即可:
    第一步:配置Php 后台允许跨域
    <?php header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
    //主要为跨域CORS配置的两大基本信息,Origin和headers
    第二步:配置Apache web服务器跨域(httpd.conf中)
    原始代码:
    <Directory />
        AllowOverride none
        Require all denied
    </Directory>
    修改代码:
    <Directory />
        Options FollowSymLinks
        AllowOverride none
        Order deny,allow
        Allow from all
    </Directory>
    JAVA后台配置
    JAVA后台配置只需要遵循如下步骤即可:
    第一步:获取依赖jar包下载 cors-filter-1.7.jar, java-property-utils-1.9.jar 这两个库文件放到lib目录下。(放到对应项目的webcontent/WEB-INF/lib/下)
    第二步:如果项目用了Maven构建的,请添加如下依赖到pom.xml中:
    <dependency>
        <groupId>com.thetransactioncompany</groupId>
        <artifactId>cors-filter</artifactId>
        <version>[ version ]</version>
    </dependency>
    NET后台配置
    .NET后台配置可以参考如下步骤:
    第一步:网站配置
    打开控制面板,选择管理工具,选择iis;右键单击自己的网站,选择浏览;打开网站所在目录,用记事本打开web.config文件添加下述配置信息,重启网站
    "Access-Control-Allow-Headers":"X-Requested-With,Content-Type,Accept,Origin"


阅读更多
个人分类: javascript基础
上一篇引用类型
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭