最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 跨域--通过代码一步一步了解其本质

    正文概述 掘金(limbo)   2021-08-02   391

    跨域--通过代码一步一步了解其本质

    跨域无论日常工作还是面试都会遇到。网上充斥着各种资料,但大多数资料都是重理论,没有实际的代码的支持,这篇文章从代码出发,轻理论重实践的讲解跨域。

    我们会使用koa搭建一个本地服务器:http://127.0.0.1:3200。 使用webpack启动本地客户端:http://127.0.0.1:3000。 探究一下前后端分离项目怎么支持CORS(跨域资源共享)。完整代码我放到了git上,阅读readme获取正确姿势。文章的主要内容如下:

    • 跨域的基础知识
    • koa搭建服务器
    • kao中间件处理跨域

    跨域的基础知识

    关于跨域的基础知识,阮一峰老师有博客: 跨域资源共享 CORS 详解介绍得很清楚,接下来我通过图文简单介绍一些理论知识。

    同源策略

    跨域--通过代码一步一步了解其本质

    跨域的反面就是同源。当协议、主机、端口相同的时候就是满足同源。

    这次搭建的例子由于端口不同,所以客服端请求的时候我们就会遇到熟悉的错误。

    Access to XMLHttpRequest at 'http://127.0.0.1:3000/user' from origin 'http://127.0.0.1:3200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
    

    两种请求及CORS策略

    了解了同源策略,我们聊聊请求。请求有复杂请求,也有简单请求。两种请求浏览器策略也不一样。一下列举了两种请求的一些例子:

    • 简单请求:请求方式为get/post
    • 复杂请求:请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json

    简单请求的跨域策略如下图 跨域--通过代码一步一步了解其本质

    1. 客户端发送简单请求
    2. 请求头带上字段Origin表明来源
    3. 服务器收到请求,在响应头设置字段:Access-Control-Allow-Origin,用于告诉客服端是否可获取资源(*表示所有来源都可以)。
    4. 跨域资源共享完成

    复杂请求的跨域策略如下图

    跨域--通过代码一步一步了解其本质

    1. 客户端发起复杂请求
    2. 对于复杂请求首先发送一个预检请求,请求你式为options
    3. 服务器接受预检请求,设置Access-Control-Allow-Origin,Access-Control-Allow-Methods,Access-Control-Allow-Headers
    4. 三个字段告诉客户端:哪些来源允许跨域,哪些请求方式允许跨域,哪些请求头允许跨域。
    5. 客户端得到上诉信息,判断是否满足条件。满足条件,发起正式请求,跨域成功。

    代码实现

    了解了以上理论信息,下面我们进入实践环节。看看koa应该怎么写代码。

    服务端

    首先使用koa/koa-router搭建一个简单的服务器。

    const Koa = require('koa')
    const Router = require('koa-router')
    
    const router = new Router() // 路由
    const app = new Koa() //创建服务器实例
    
    
    router.get('/name', async (ctx) => {
      ctx.body = {
        name: 'miujg',
        age: 26
      }
    })
    
    app.use(router.routes())
    app.use(router.allowedMethods()) // 注册路由
    
    app.listen(3000, ()=>{
      console.log('serve start on 3000')
    })
    
    

    客户端

    我这里客户端是使用webpack、webpack-dev-server启动的一个服务。发起请求js代码如下

    const axios = require("axios")
    
    axios.get('http://127.0.0.1:3000/name').then(rs => {
      console.log(rs)
    })
    
    

    实际效果如下:

    跨域--通过代码一步一步了解其本质

    简单请求中间件设置

    由之前的理论知识我们可以知道,对于简单请求,如果服务器在响应头中设置Access-Control-Allow-Origin,就能达到效果。

    这时我们就会想到koa的中间件,中间件的目的是在响应头上设置Access-Control-Allow-Origin字段

    代码实现如下:

    const Koa = require('koa')
    const Router = require('koa-router')
    
    const router = new Router()
    const app = new Koa()
    
    // 简单请求跨域处理
    app.use(async (ctx, next) => {
      ctx.response.set('Access-Control-Allow-Origin', '*') // *标识允许所有来源,也可以设置数组
      next()
    })
    
    router.get('/name', async (ctx) => {
      ctx.body = {
        name: 'miujg'
      }
    })
    
    app.use(router.routes())
    app.use(router.allowedMethods())
    
    app.listen(3000, ()=>{
      console.log('serve start on 3000')
    })
    
    

    请求效果如下:

    跨域--通过代码一步一步了解其本质

    跨域--通过代码一步一步了解其本质

    可以发现响应头中设置了Access-Control-Allow-Origin,简单请求跨域资源共享成功。

    复杂请求中间件设置

    在以上代码的基础上,我们发起一个put请求。put为一个复杂请求

    axios.put('http://127.0.0.1:3000/name').then(rs => {
      console.log(rs)
    })
    

    后端加一个put接口

    router.put('/name', async (ctx) => {
      ctx.body = {
        name: 'miujg--put',
        age: 29
      }
    })
    

    实际情况如下:

    跨域--通过代码一步一步了解其本质

    跨域--通过代码一步一步了解其本质

    直接看报错:put方法不被允许,需要在options响应头中添加字段Access-Control-Allow-Methods。我们改造一下中间件:

    app.use(async (ctx, next) => {
      ctx.response.set('Access-Control-Allow-Origin', '*')
      if(ctx.request.method == 'OPTIONS') {
        ctx.status = 204
        ctx.response.set('Access-Control-Allow-Methods', ['GET', 'PUT', 'POST', 'DELETE'])
        ctx.response.set('Access-Control-Allow-Headers', ['Content-Type', 'Accept'])
      }
      next()
    })
    

    浏览器效果如下: 跨域--通过代码一步一步了解其本质 跨域--通过代码一步一步了解其本质

    备注:不同的复杂请求,响应头设置的值也可能不一样。

    到此我们从代码层面搞清楚怎么处理跨域了,在实际开发中,只需要引进koa-cors就行了。这里就不多介绍。

    小结

    要深刻理解跨域,首先要搞清楚理论知识,知道浏览器的跨域资源共享是一个怎么策略。然后本地模拟客户端和服务器,在火狐浏览器中看效果。我相信,有了编码这个过程,你能更深刻理解跨域。


    下载网 » 跨域--通过代码一步一步了解其本质

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元