• 推动长江经济带发展 习近平要求境界和担当 2019-11-11
  • 丰台东铁匠营街道:品粽赏乐感受改革开放四十周年 2019-11-11
  • 学习宣传宪法 弘扬法治精神 2019-11-07
  • 山东搭建“灯塔—党建在线”网络平台 2019-11-07
  • 2016杨宗纬VOCAL巡演北京站正式开票杨宗纬VOCAL 2019-11-04
  • 年龄大了,也想积点口德,已经给你笔下留情了。 2019-11-04
  • 人民网通行证——帮助 2019-11-03
  • 端午节,跟随习近平找寻中华民族“精气神” 2019-10-30
  • 天津加入抢人大战,你会否挑花眼? 2019-10-29
  • “海河英才”行动计划为企业解渴 2019-10-29
  • 在庆祝海南建省办经济特区30周年大会上的讲话 2019-10-07
  • 俄罗斯世界杯F组:球迷风采 2019-09-24
  • 彭于晏廖凡曝姜文“精神洁癖” 2019-09-24
  • 苏州大学研究生支教团网上众筹资助留守儿童 2019-09-23
  • 湖北政务微信排行榜第187期出炉 交警类公号表现亮眼 2019-09-19
  • 香港赛马会动画玄机片:浅谈Koa2框架利用CORS完成跨域ajax请求

     更新时间:2018年03月06日 08:37:07   作者:黄天浩   我要评论
    这篇文章主要介绍了浅谈Koa2框架利用CORS完成跨域ajax请求,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    香港赛马会网站惠泽社绝杀八码 www.mwcrz.tw 实现跨域ajax请求的方式有很多,其中一个是利用CORS,而这个方法关键是在服务器端进行配置。

    本文仅对能够完成正??缬騛jax响应的,最基本的配置进行说明(深层次的配置我也不会)。

    CORS将请求分为简单请求和非简单请求,可以简单的认为,简单请求就是没有加上额外请求头部的get和post请求,并且如果是post请求,请求格式不能是application/json(因为我对这一块理解不深如果错误希望能有人指出错误并提出修改意见)。而其余的,put、post请求,Content-Type为application/json的请求,以及带有自定义的请求头部的请求,就为非简单请求。

    简单请求的配置十分简单,如果只是完成响应就达到目的的话,仅需配置响应头部的Access-Control-Allow-Origin即可。

    如果我们在//localhost:3000 域名下想要访问 //127.0.0.1:3001 域名??梢宰鋈缦屡渲茫?/p>

    app.use(async (ctx, next) => {
     ctx.set('Access-Control-Allow-Origin', '//localhost:3000');
     await next();
    });
    

    然后用ajax发起一个简单请求,例如post请求,就可以轻松的得到服务器正确响应了。

    实验代码如下:

    $.ajax({
      type: 'post',
      url: '//127.0.0.1:3001/async-post'
     }).done(data => {
      console.log(data);
    })
    

    服务器端代码:

    router.post('/async-post',async ctx => {
     ctx.body = {
     code: "1",
     msg: "succ"
     }
    });
    

    然后就能得到正确的响应信息了。

    这时候如果看一下请求和响应的头部信息,会发现请求头部多了个origin(还有一个referer为发出请求的url地址),而响应头部多了个Access-Control-Allow-Origin。

    现在可以发送简单请求了,但是要想发送非简单请求还是需要其他的配置。

    当第一次发出非简单请求的时候,实际上会发出两个请求,第一次发出的是preflight request,这个请求的请求方法是OPTIONS,这个请求是否通过决定了这一个种类的非简单请求是否能成功得到响应。

    为了能在服务器匹配到这个OPTIONS类型的请求,因此需要自己做一个中间件来进行匹配,并给出响应使得这个预检能够通过。

    app.use(async (ctx, next) => {
     if (ctx.method === 'OPTIONS') {
     ctx.body = '';
     }
     await next();
    });
    

    这样OPTIONS请求就能够通过了。

    如果检查一下preflight request的请求头部,会发现多了两个请求头。

    Access-Control-Request-Method: PUT
    Origin: //localhost:3000

    要通过这两个头部信息与服务器进行协商,看是否符合服务器应答条件。

    很容易理解,既然请求头多了两个信息,响应头自然也应该有两个信息相对应,这两个信息如下:

    Access-Control-Allow-Origin: //localhost:3000
    Access-Control-Allow-Methods: PUT,DELETE,POST,GET

    第一条信息和origin相同因此通过。第二条信息对应Access-Controll-Request-Method,如果在请求的方式包含在服务器允许的响应方式之中,因此这条也通过。两个约束条件都满足了,所以可以成功的发起请求。

    至此为止,相当于仅仅完成了预检,还没发送真正的请求呢。

    真正的请求当然也成功获得了响应,并且响应头如下(省略不重要部分)

    Access-Control-Allow-Origin: //localhost:3000
    Access-Control-Allow-Methods: PUT,DELETE,POST,GET

    请求头如下:

    Origin: //localhost:3000

    这就很显而易见了,响应头部信息是我们在服务器设定的,因此是这样。

    而客户端因为刚才已经预检过了,所以不需要再发Access-Control-Request-Method这个请求头了。

    这个例子的代码如下:

    $.ajax({
       type: 'put',
       url: '//127.0.0.1:3001/put'
      }).done(data => {
       console.log(data);
    });
    

    服务器代码:

    app.use(async (ctx, next) => {
      ctx.set('Access-Control-Allow-Origin', '//localhost:3000');
      ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET');
      await next();
    });
    

    至此我们完成了能够正确进行跨域ajax响应的基本配置,还有一些可以进一步配置的东西。

    比如,到目前为止,每一次非简单请求都会实际上发出两次请求,一次预检一次真正请求,这就比较损失性能了。为了能不发预检请求,可以对如下响应头进行配置。

    Access-Control-Max-Age: 86400

    这个响应头的意义在于,设置一个相对时间,在该非简单请求在服务器端通过检验的那一刻起,当流逝的时间的毫秒数不足Access-Control-Max-Age时,就不需要再进行预检,可以直接发送一次请求。

    当然,简单请求时没有预检的,因此这条代码对简单请求没有意义。

    目前代码如下:

    app.use(async (ctx, next) => {
     ctx.set('Access-Control-Allow-Origin', '//localhost:3000');
     ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET');
     ctx.set('Access-Control-Max-Age', 3600 * 24);
     await next();
    });
    

    到现在为止,可以对跨域ajax请求进行响应了,但是该域下的cookie不会被携带在请求头中。如果想要带着cookie到服务器,并且允许服务器对cookie进一步设置,还需要进行进一步的配置。

    为了便于后续的检测,我们预先在//127.0.0.1:3001这个域名下设置两个cookie。注意不要错误把cookie设置成中文(刚才我就设置成了中文,结果报错,半天没找到出错原因)

    然后我们要做两步,第一步设置响应头Access-Control-Allow-Credentials为true,然后在客户端设置xhr对象的withCredentials属性为true。

    客户端代码如下:

    $.ajax({
       type: 'put',
       url: '//127.0.0.1:3001/put',
       data: {
        name: '黄天浩',
        age: 20
       },
       xhrFields: {
        withCredentials: true
       }
      }).done(data => {
       console.log(data);
      });
    

    服务端如下:

    app.use(async (ctx, next) => {
      ctx.set('Access-Control-Allow-Origin', '//localhost:3000');
      ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET');
      ctx.set('Access-Control-Allow-Credentials', true);
      await next();
    });
    

    这时就可以带着cookie到服务器了,并且服务器也可以对cookie进行改动。但是cookie仍是//127.0.0.1:3001域名下的cookie,无论怎么操作都在该域名下,无法访问其他域名下的cookie。

    现在为止CORS的基本功能已经都提到过了。

    一开始我不知道怎么给Access-Control-Allow-Origin,后来经人提醒,发现可以写一个白名单数组,然后每次接到请求时判断origin是否在白名单数组中,然后动态的设置Access-Control-Allow-Origin,代码如下:

    app.use(async (ctx, next) => {
     if (ctx.request.header.origin !== ctx.origin && whiteList.includes(ctx.request.header.origin)) {
      ctx.set('Access-Control-Allow-Origin', ctx.request.header.origin);
      ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET');
      ctx.set('Access-Control-Allow-Credentials', true);
      ctx.set('Access-Control-Max-Age', 3600 * 24);
     }
     await next();
    });
    

    这样就可以不用*通配符也可匹配多个origin了。

    注意:ctx.origin与ctx.request.header.origin不同,ctx.origin是本服务器的域名,ctx.request.header.origin是发送请求的请求头部的origin,二者不要混淆。

    最后,我们再稍微调整一下自定义的中间件的结构,防止每次请求都返回Access-Control-Allow-Methods以及Access-Control-Max-Age,这两个响应头其实是没有必要每次都返回的,只是第一次有预检的时候返回就可以了。

    调整后顺序如下:

    app.use(async (ctx, next) => {
     if (ctx.request.header.origin !== ctx.origin && whiteList.includes(ctx.request.header.origin)) {
      ctx.set('Access-Control-Allow-Origin', ctx.request.header.origin);
      ctx.set('Access-Control-Allow-Credentials', true);
     }
     await next();
    });
    
    app.use(async (ctx, next) => {
     if (ctx.method === 'OPTIONS') {
      ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET');
      ctx.set('Access-Control-Max-Age', 3600 * 24);
      ctx.body = '';
     }
     await next();
    });
    
    

    这样就减少了多余的响应头。

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    相关文章

    • 独立部署小程序基于nodejs的服务器过程详解

      独立部署小程序基于nodejs的服务器过程详解

      这篇文章主要介绍了独立部署小程序基于nodejs的服务器过程详解,完全自定义的部署小程序服务器, 不依托于腾讯云服务器体系. 以阿里云服务器为基础建立.服务器语言选用nodejs.,需要的朋友可以参考下
      2019-06-06
    • NodeJs form-data格式传输文件的方法

      NodeJs form-data格式传输文件的方法

      这篇文章主要介绍了NodeJs form-data格式传输文件的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
      2017-12-12
    • node.js中的fs.rmdir方法使用说明

      node.js中的fs.rmdir方法使用说明

      这篇文章主要介绍了node.js中的fs.rmdir方法使用说明,本文介绍了fs.rmdir方法说明、语法、接收参数、使用实例和实现源码,需要的朋友可以参考下
      2014-12-12
    • Node.js中安全调用系统命令的方法(避免注入安全漏洞)

      Node.js中安全调用系统命令的方法(避免注入安全漏洞)

      这篇文章主要介绍了Node.js中安全调用系统命令的方法(避免注入安全漏洞),本文讲解的一般是连接字符串会时出的安全问题情况,需要的朋友可以参考下
      2014-12-12
    • node中实现删除目录的几种方法

      node中实现删除目录的几种方法

      这篇文章主要介绍了node中实现删除目录的几种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
      2019-06-06
    • NodeJS搭建HTTP服务器的实现步骤

      NodeJS搭建HTTP服务器的实现步骤

      NodeJS中用来创建服务的??槭莌ttp核心???,本篇就来介绍关于使用http??榇罱℉TTP服务器和客户端的方法,以及??榈幕?API,非常具有实用价值,需要的朋友可以参考下
      2018-10-10
    • express中static中间件的具体使用方法

      express中static中间件的具体使用方法

      这篇文章主要介绍了express中static中间件的具体使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
      2019-10-10
    • Node.js编写CLI的实例详解

      Node.js编写CLI的实例详解

      Node.js的应用场景有前后端分离、海量web页面渲染服务、命令行工具和桌面端应用等等。本篇文章选取CLI(Command Line Tools)子领域,来谈谈Node.js编写CLI的实践,让CLI切实解决实际工程问题。
      2017-05-05
    • Node.js应用设置安全的沙箱环境

      Node.js应用设置安全的沙箱环境

      这篇文章主要介绍了Node.js应用设置安全的沙箱环境的方法以及注意事项,对此有需要的朋友可以参考学习下。
      2018-04-04
    • Node.js中child_process实现多进程

      Node.js中child_process实现多进程

      这篇文章主要介绍了Node.js中child_process实现多进程,需要的朋友可以参考下
      2015-02-02

    最新评论

  • 推动长江经济带发展 习近平要求境界和担当 2019-11-11
  • 丰台东铁匠营街道:品粽赏乐感受改革开放四十周年 2019-11-11
  • 学习宣传宪法 弘扬法治精神 2019-11-07
  • 山东搭建“灯塔—党建在线”网络平台 2019-11-07
  • 2016杨宗纬VOCAL巡演北京站正式开票杨宗纬VOCAL 2019-11-04
  • 年龄大了,也想积点口德,已经给你笔下留情了。 2019-11-04
  • 人民网通行证——帮助 2019-11-03
  • 端午节,跟随习近平找寻中华民族“精气神” 2019-10-30
  • 天津加入抢人大战,你会否挑花眼? 2019-10-29
  • “海河英才”行动计划为企业解渴 2019-10-29
  • 在庆祝海南建省办经济特区30周年大会上的讲话 2019-10-07
  • 俄罗斯世界杯F组:球迷风采 2019-09-24
  • 彭于晏廖凡曝姜文“精神洁癖” 2019-09-24
  • 苏州大学研究生支教团网上众筹资助留守儿童 2019-09-23
  • 湖北政务微信排行榜第187期出炉 交警类公号表现亮眼 2019-09-19
  • 11选五定两胆技巧 领航彩票APP 关东煮人情店物语3汉化 雪缘园即时比分直播 网赌把自己赌废了2018 大乐透19098期推荐 金拉霸老虎机怎么玩 拼多多签到满十元怎么提现 彩票计划软件手机版免费 188篮球比分直播吧