|
CORS 的存在是为了保护互联网免受黑客攻击。
说真的,在这说点儿题外话,讲讲它的历史。
多年来,来自一个网站的脚本无法访问另一个网站的内容。
这个简单有力的规则是互联网安全的基础。例如,来自 hacker.com 的脚本无法访问 gmail.com 上的用户邮箱。基于这样的规则,人们感到很安全。
在那时候,JavaScript 并没有任何特殊的执行网络请求的方法。它只是一种用来装饰网页的玩具语言而已。
但是 Web 开发人员需要更多功能。人们发明了各种各样的技巧去突破该限制,并向其他网站发出请求。
使用表单
其中一种和其他服务器通信的方法是在那里提交一个 <form>。人们将它提交到 <iframe>,只是为了停留在当前页面,像这样:
<!-- 表单目标 -->
<iframe name="iframe"></iframe>
<!-- 表单可以由 JavaScript 动态生成并提交 -->
<form target="iframe" method="POST" action="http://another.com/…">
...
</form>
因此,即使没有网络方法,也可以向其他网站发出 GET/POST 请求,因为表单可以将数据发送到任何地方。但是由于禁止从其他网站访问 <iframe> 中的内容,因此就无法读取响应。
确切地说,实际上有一些技巧能够解决这个问题,这在 iframe 和页面中都需要添加特殊脚本。因此,与 iframe 的通信在技术上是可能的。现在我们没必要讲其细节内容,我们还是让这些古董代码不要再出现了吧。
使用 script
另一个技巧是使用 script 标签。script 可以具有任何域的 src,例如 <script src="http://another.com/…">。也可以执行来自任何网站的 script。
如果一个网站,例如 another.com 试图公开这种访问方式的数据,则会使用所谓的 “JSONP (JSON with padding)” 协议。
这是它的工作方式。
假设在我们的网站,需要以这种方式从 http://another.com 网站获取数据,例如天气:
首先,我们先声明一个全局函数来接收数据,例如 gotWeather。
// 1. 声明处理天气数据的函数
function gotWeather({ temperature, humidity }) {
alert(`temperature: ${temperature}, humidity: ${humidity}`);
}
然后我们创建一个特性(attribute)为 src="http://another.com/weather.json?callback=gotWeather" 的 <script> 标签,使用我们的函数名作为它的 callback URL-参数。
let script = document.createElement('script');
script.src = `http://another.com/weather.json?callback=gotWeather`;
document.body.append(script);
远程服务器 another.com 动态生成一个脚本,该脚本调用 gotWeather(...),发送它想让我们接收的数据。
// 我们期望来自服务器的回答看起来像这样:
gotWeather({
temperature: 25,
humidity: 78
});
当远程脚本加载并执行时,gotWeather 函数将运行,并且因为它是我们的函数,我们就有了需要的数据。
这是可行的,并且不违反安全规定,因为双方都同意以这种方式传递数据。而且,既然双方都同意这种行为,那这肯定不是黑客攻击了。现在仍然有提供这种访问的服务,因为即使是非常旧的浏览器它依然适用。
不久之后,网络方法出现在了浏览器 JavaScript 中。
起初,跨源请求是被禁止的。但是,经过长时间的讨论,跨源请求被允许了,但是任何新功能都需要服务器明确允许,以特殊的 header 表述。
|
|