跨域问题

2021-08-11 | 12分钟 | yrobot | 浏览器,跨域,CORS,安全,前端

跨域限制仅仅是浏览器的行为吗

是的。

跨域限制是浏览器为了信息安全所产生的规则。

跨域问题其实就是浏览器的同源策略导致的。

而利用 nodejs 发送请求是不存在跨域问题的,因为都没有当前域的概念。

浏览器的同源策略

同源策略是一个重要的安全策略,它用于限制一个 origin 的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。 --来源 MDN

同源的判断:protocol(协议)、domain(域名)、port(端口)三者一致。

浏览器的跨域限制有哪些

对于不同源的站点,浏览器会有以下限制:

  1. 不允许直接请求跨域接口

    • 不允许发送 POST 请求:在发送 POST 请求之前会发送 OPTIONS 请求,HTTP 响应状态码为 403(Forbidden)
    • 允许发送 GET 请求:HTTP 响应状态码为 200,但是不能读取服务器返回的数据(使用 <img/> 发送 GET 请求)
  2. 不允许访问跨域的 DOM,Cookie,XMLHttpRequest

  3. 不能访问跨源 localStorage,sessionStorage

    浏览器会使用当前域名作为 key 来存数据


所以,由于浏览器 同源策略,非同源的 js 代码

  1. 无法直接在非同源网站发送跨域请求。
  2. 无法自己读取非同源 iframe 页面的 DOM 内容,包括 DOM 种的信息。
  3. 无法访问非同源网站在本地存储的数据

近几年浏览器对于 CSRF 的防御提升,跨域请求携带 cookie 存在限制

下图是我用常规手段配置跨域后,设置 cookie 时 chrome 的错误提示:

新版 Chrome(Chrome 80+)会对跨域请求携带 cookie 进行以下校验,只有全通过后才可以跨域携带 cookie:

  1. 服务端 cookie 设置 SameSite=None
  2. 服务端 cookie 设置 Secure
  3. 请求通过 https 协议进行

解决跨域

跨域限制是浏览器为了信息安全所产生的规则

所以 纯前端解决跨域的方案都是不可靠的

其实最直白的方式就是,服务器告诉浏览器,当前域名是可以从我这获取数据的。
也就是配置 response.headerAccess-Control-Allow-Origin
当然处于安全考虑还是不建议设为*,也就是允许所有域名的请求。这样设置,直接关闭了浏览器跨域请求当前服务的安全控制

建议解决方案:

  1. 设置一个请求域名白名单:
  • 可以直接在 Nginx 反代理时判断请求 origin 是否在白名单中,从而转发到真实的应用服务器。当然此时的应用服务器需要直接设置Access-Control-Allow-Origin*或者域名白名单。
  • 或者直接在应用服务里利用 middleware 判断 origin 是否在白名单中,来控制请求是否被 forbidden