Ajax跨域总结

daoen 2019-05-10 PM 3373℃ 1条

前言

在前后端分离开发模式下,Ajax跨域是一个常见的问题,本文梳理了一下Ajax跨域相关知识,做一个小总结

1.为什么会跨域?

浏览器同源政策及其规避方法(阮一峰)
浏览器为了保证用户信息的安全,防止恶意的网站窃取数据,引入同源策略,同源指的是"三个相同":

  • 协议相同
  • 域名相同
  • 端口相同

如果非同源,AJAX 请求不能发送。

2.ajax跨域情景复现

案例一:
cors_1.PNG

出现这种情况的原因如下:

本次ajax请求是“非简单请求”,所以请求前会发送一次预检请求(OPTIONS)

服务器端后台接口没有允许OPTIONS请求,导致无法找到对应接口地址

解决方案: 后端允许options请求

案例二:
cors_20.PNG

cors_21.PNG

这种现象和第一种和第二种有区别,这种情况下,服务器端后台允许OPTIONS请求,并且接口也允许OPTIONS请求,但是头部出现不匹配现象,因为我们自定义了头部x-token,而后端没有相应的设置

解决方案: 后端增加对应的头部支持

3.如何解决ajax跨域

一般ajax跨域解决就是通过JSONP解决或者CORS解决

JSONP方式解决跨域问题

JSONP解决跨域问题是一个比较古老的方案(实际中不推荐使用),这里做简单介绍(实际项目中如果要使用JSONP,一般会使用JQ等对JSONP进行了封装的类库来进行ajax请求)

实现原理
JSONP之所以能够用来解决跨域方案,主要是因为 <script> 脚本拥有跨域能力,而JSONP正是利用这一点来实现。具体原理如图

实现流程

JSONP的实现步骤大致如下(参考了来源中的文章)

客户端网页网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制

  function addScriptTag(src) {
    var script = document.createElement('script');
    script.setAttribute("type","text/javascript");
    script.src = src;
    document.body.appendChild(script);
  }
    
  window.onload = function () {
    addScriptTag('http://example.com/ip?callback=foo');
  }
    
  function foo(data) {
    console.log('response data: ' + JSON.stringify(data));
  };                      

请求时,接口地址是作为构建出的脚本标签的src的,这样,当脚本标签构建出来时,最终的src是接口返回的内容

服务端对应的接口在返回参数外面添加函数包裹层

foo({
  "test": "testData"
});  

由于<script>元素请求的脚本,直接作为代码运行。这时,只要浏览器定义了foo函数,该函数就会立即调用。作为参数的JSON数据被视为JavaScript对象,而不是字符串,因此避免了使用JSON.parse的步骤。

注意,一般的JSONP接口和普通接口返回数据是有区别的,所以接口如果要做JSONO兼容,需要进行判断是否有对应callback关键字参数,如果有则是JSONP请求,返回JSONP数据,否则返回普通数据

基于JSONP的实现原理,所以JSONP只能是“GET”请求,不能进行较为复杂的POST和其它请求,所以遇到那种情况,就得参考下面的CORS解决跨域了

CORS解决跨域问题

CORS的原理上文中已经介绍了,这里主要介绍的是,实际项目中,后端应该如何配置以解决问题(因为大量项目实践都是由后端进行解决的),这里整理了一些常见的后端解决方案:

PHP后台配置

<?php
// 主要为跨域CORS配置的两大基本信息,Origin和headers
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Methods:GET,POST,OPTIONS,DELETE");
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');

CORS解决方案有一个缺点就是不可避免的OPTIONS请求,增加了网络损耗,可以使用以下配置缓存请求,减少OPTIONS请求次数:

header("Access-Control-Max-Age: 100");数值单位为秒

代理请求方式解决接口跨域问题

与前面的方法不同,前面CORS是后端解决,而这个主要是前端对接口进行代理,也就是:

前端ajax请求的是本地接口,本地接口接收到请求后向实际的接口请求数据,然后再将信息返回给前端

一般用node.js即可代理,以webpack3.*版本为例,实现如下:

 proxyTable: {
      '/api':{
        target: "http://example.com",
        changeOrigin: true,
      }
    },

也可以使用nginx代理,配置如下:

location /api {
    proxy_pass http://example.com;
    root   html;
    index  index.html index.htm;
}
标签: ajax

非特殊说明,本博所有文章均为博主原创。

评论啦~



唉呀 ~ 仅有一条评论


  1. 小新
    小新

    urepjk48652KQ-文章很不错,感谢作者!https://kan.xiaoxinbk.com/4683.html/

    回复 2024-09-25 06:11