写点什么

CORS 跨域问题

作者:Geek_7a170c
  • 2023-11-27
    北京
  • 本文字数:2042 字

    阅读完需:约 7 分钟

云服务器 89 元/年,这里有专享低价:https://www.aliyun.com/minisite/goods?userCode=f0xyki07&share_source=copy_link


先了解几个概念:


同源策略 (Same-origin policy)


是 Web 应用程序安全模型中的一个重要概念。根据该策略,Web 浏览器允许第一个 Web 页面中包含的脚本访问第二个 Web 页面中的数据,但前提是两个 Web 页面具有相同的源。同源定义为 URI 具有相同协议、域名和端口号。此策略可防止一个页面上的恶意脚本通过该页面的文档对象模型访问另一个网页上的敏感数据。这种机制对于广泛依赖于 HTTP Cookie 来维护经过身份验证的用户会话的现代 Web 应用程序具有特别重要的意义,因为服务器基于 HTTP Cookie 信息来发布敏感信息或采取状态改变操作。必须在客户端维护由不相关站点提供的内容之间的严格分离,以防止数据机密性或完整性的丢失。同源策略主要适用于脚本的数据访问; 通过相应的 HTML 标签在源(例如图像, CSS 和脚本)之间嵌入资源不受限制(字体是一个值得注意的例外)。


JSONP (JSON with padding)


是数据格式 JSON 的一种“使用模式”,可以让网页从别的网域要数据。由于同源策略,一般来说位于 server1.com 的网页无法与 server2.com 的服务器沟通,而 HTML 的 <script> 元素是一个例外。利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 数据,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的数据并不是 JSON ,而是任意的 JavaScript ,用 JavaScript 解释器运行而不是用 JSON 解析器解析。风险是易受到跨站请求伪造(CSRF/XSRF)的攻击


跨来源资源共享 (Cross-Origin Resource Sharing, CORS)


是一份浏览器技术的规范,提供了 Web 服务从不同网域传来沙盒脚本的方法,以避开浏览器的同源策略,是 JSONP 模式的现代版。与 JSONP 不同,CORS 除了 GET 请求方法以外也支持其他的 HTTP 请求。用 CORS 可以让网页设计师用一般的 XMLHttpRequest ,这种方式的错误处理比 JSONP 要来的好。另一方面,JSONP 可以在不支持 CORS 的老旧浏览器上运作。现代的浏览器都支持 CORS。


简单的说:跨域就是当浏览器向 (domain-a.com) 请求了一个资源后,该资源又去请求 (domain-b.com) 上的另一个资源时,就会发起一个跨域 HTTP 请求。 (domain-a、domain-b 的协议、域名、端口有一样不同)


以前涉及到的网站项目都是前后端在一块的(同一个服务器同一个域名下),访问的时候由 php 进行跳转页面、控制页面的输出,JavaScript 顶多发个 ajax 请求数据,不涉及到前端自己保存登录状态,也不会涉及到跨域问题。随着前端的发展,特别是 nodejs 的出现后,由 nodejs 启动服务,前端可以不依赖后端,前端自己跑自己的业务,然后在需要数据的时候发个 ajax 去调用后端接口去取数据,所以这就是前后端分离,前端专注前端的业务,后端专注于提供自己的接口。在前后端分离的基础上,前端和后端有可能不是同一个服务器、不是同一个域名,这时候就会有跨域的问题。


CORS 规范让 Web 应用服务器能支持跨站访问控制,从而使得安全地进行跨站数据传输成为可能。需要特别注意的是,这个规范是针对 API 容器的(比如说 XMLHttpReques 或者 Fetch),以减轻跨域 HTTP 请求的风险。CORS 需要客户端和服务器同时支持。目前,所有现代浏览器都支持该机制。


CORS 允许在下列场景中使用跨域 HTTP 请求:


  • 前文提到的由 XMLHttpRequest 或 Fetch 发起的跨域 HTTP 请求。

  • Web 字体 (CSS 中通过 @font-face 使用跨域字体资源), 因此,网站就可以发布 TrueType 字体资源,并只允许已授权网站进行跨站调用。

  • WebGL 贴图

  • 使用 drawImage 将 Images/video 画面绘制到 canvas

  • 样式表(使用 CSSOM)

  • Scripts (未处理的异常)


CORS 的请求种类:简单请求、预检请求及附带身份凭证的请求,详细可看:



解决方案


  • 配置代理服务器, Node.js 代理、Nginx 代理

  • spring framework 已提供 CORS 支持,可以通过引入注解 @CrossOrigin,或者设置全局 Cors 配置来允许跨域访问。详细见 Spring Boot Reference Guide

  • 服务器端设置:在 Controller 返回的 Rsponse 添加 Header :Access-Control-Allow-Origin: ** 代表允许所有域的访问,也可指定域。


Form 表单里面发送请求为什么会没有跨域?


首先,表单的提交方式有两种,一种是直接指定表单的 action。一种是 ajax 接手控制请求。


直接使用 action 的时候,是直接把请求交给了 action 里面的域,本身页面不会去管他的请求结果,后面的步骤就已经离开了原来的域,进入了 action 里面的域。例如:


<form action="baidu.com">    // your form filed</form>
复制代码


上面这个表单提交后,剩余的操作就交给了 action 里面的域 baidu.com,本页面的逻辑


和这个表单没啥关系,由于不关系请求的响应,所以浏览器认为是安全的。


而使用 ajax 来控制 form 的请求的时候,页面 js 需要知道请求的返回值,这个时候,浏览器成功发出跨域请求,但需要获得授权才可以成功请求,否则返回结果会被浏览器拦截。


微前端 - 将微服务理念延伸到前端开发中


参考:


同源策略跨域资源共享MDN

发布于: 刚刚阅读数: 2
用户头像

Geek_7a170c

关注

还未添加个人签名 2020-09-01 加入

还未添加个人简介

评论

发布
暂无评论
CORS跨域问题_Geek_7a170c_InfoQ写作社区