0

    CORS 是什么?它的工作机理是什么?

    2023.07.24 | admin | 133次围观

    你好!如果你翻到这里,我相信你可能遇到过:在做 API 借口调试时,浏览器 console 框莫名其妙地报出 CORS 相关的错误。今天,我们将会对这些错误是什么,并且如何解决这些错误进行探究。

    我们的浏览器里边有一些安全策略,以保证数据传输的安全性,并且在传送抵达终端用户前,保证其不存在攻击数据的行为。现代浏览器具备的其中一项策略称为 same-origin policy(同源策略),也就是:在同源上的资源才能被网页端用户访问到。

    首先让我们看看同源是什么

    例如,我们有以下几个网站

    :4000

    这些网站不是同源的,因为它们有不一样的端口、协议、域名,而一个网站要想是同源的,它必须有相同的协议、域名和端口号。协议(例如 https http) 和 域名(例如 example.in 或者 exaple.com)。我们知道我们的网站运行在不同的端口上,但是端口号也需要一样(才能满足同源)。

    现在浏览器工作原理是怎样的,让我们假设,你正在从源 :3000 请求,可是你的资源在源为exampleAPI.com/的服务上放着,那么你就会得到 CORS 报错,正是因为浏览器有同源策略,而你正在从不同的源请求(数据,图片等等)。

    如何解决这些报错

    通过(在所访问的)资源所在的服务端修改一些配置,错误就可得以解决。例如,你正在开发一个全栈 web 应用,前端使用的是 Reactjs,后端使用 Node JS 提供 APIs(Application Interfaces 应用接口)。现在,当你从客户端请求(数据),由于源不匹配,就出现了(跨域)错误。服务端需要在返回(response)中指定允许访问的源,浏览器才能察觉到,并不阻拦返回的数据,因而解决 CORS 错误。

    不论后端使用使用的什么语言框架如,Django、Node 或者 C#,我们仅需要在服务端配置(server config)中添加允许(跨域)的源,这样服务端(server)会在返回体中发送一个特定的参数——Access-Control-Allow-Origin。

    如图,我们可以看到,当使用 Access-Control-Allow-Origin : * 这个参数时,浏览器知道了允许访问这个资源的源,而 * 则表示任何源都可以访问这个资源。当然,我们也可以设置一个允许访问一些资源的源的数组

    这里有一些在 Node\Express 应用中跨域的代码片段,你需要使用命令行 npm install cors 安装 cors 包。

    CORS 是什么?它的工作机理是什么?

    然后,你仅用执行 app.use() 然后传入 cors 函数进去。

    这个 cors 函数接受一个对象作为参数,对象中你需要添加键值对:origin: *,你也可以指定一个允许(跨域)源的数组作为键值对的值。并不推荐使用 *,因为它允许所有源访问资源(如果都设置 * ,同源策略就无意义了),通常情况是提供一个列有允许访问源的数组。

    预检请求(Preflight request)

    CORS 预检请求是一个CORS请求,它用来检查 CORS 协议在服务端是否被支持浏览器工作原理是怎样的,服务端是否理解特定的(请求)方法和头部。

    因此,便有了两种基本类型的请求

    简单请求预检请求

    使用如 GET、HEAD、POST 方法的请求是简单请求,因为这些请求没有在服务端产生副作用。通常情况下,GET 请求会从服务端获取数据,POST 请求会在服务端创建新的数据,但是他们都不会替换在服务端已经存在的数据。

    使用如:DELETE 或者 PUT 方法的请求是预检请求,因为当使用这些方法时,任何人都可以修改或者删除已经存在服务端的数据,从而产生副作用,浏览器端在发送真实的请求前,它们会发生预检请求,并携带 access-control-allow-method 和 access-control-allow-headers,这些头部字段用来检查服务端是否允许使用这些方法,是否允许这些操作执行,如果服务端返回 200 状态,就表明预检请求验证通过,浏览器端菜开始发送真正的请求。

    希望现在你对 CORS 已经有了更好的理解,并且能够解决这些跨域错误,继续加油!

    译者注:

    其实跨域的情况经常遇到,尤其是开发中,因为本地都是 localhost 的域名,而为了验证效果,要么专门搭建测试环境填入 mock 数据,另外常用的就是设置 Access-Control-Allow-Origin 实现跨域。

    对于预检请求,作者其实说的有点片。简单请求和非简单请求并非仅靠请求方法就可以区分,大家可以去搜索“CORS 简单请求 非简单请求”,就可以看到比较详细的介绍。

    其次理解为啥预检请求要先理解什么是副作用,这些含有副作用的操作会导致服务端现有的数据修改或者删除,操作风险高所以需要先执行预检请求,保证后续真实请求的可靠性。

    版权声明

    本文仅代表作者观点。
    本文系作者授权发表,未经许可,不得转载。

    发表评论