fly6022
文章9
标签17
分类2
Ajax 同源策略限制问题的解决

Ajax 同源策略限制问题的解决

Ajax 同源策略限制问题的解决。

01

写在前面

首先,我们要了解,何为『同源策略』。

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

如果两个 URL 的 protocol、port (如果有指定的话)和 host 都相同的话,则这两个 URL 是同源。这个方案也被称为“协议/主机/端口元组”,或者直接是 “元组”。(“元组” 是指一组项目构成的整体,双重/三重/四重/五重/等的通用形式)。

—— MDN官方文档

例如:

URL 结果 原因
http://a.com/1.html 同源 只有路径不同
http://a.com/src/2.html 同源 只有路径不同
https://a.com/3.html 失败 协议不同
http://a.com:81/4.html 失败 端口不同 (http://默认端口是80)
http://b.com/1.html 失败 主机不同

总结一下,满足同源的条件:

  • 主机相同
  • 端口相同
  • 协议相同

三者缺一不可。

解决方法

我们已经了解了『同源策略』的基本概念,虽然说,它是一种浏览器主动的安全策略,但是,却时常给我们的前端开发造成了困难。

那么,我们如何解决『同源策略』给我们带来的不便呢?

我比较推荐的方法有两种。

JSONP

JSONP 是利用html标签不受『同源策略』限制的影响,从而达到解决『同源策略』限制的目的。通俗来讲,叫“曲线救国”。

但是,这种方法是有一定的局限性的:它仅支持GET方式请求数据。

这种方法的好处是:

  • 比较简单
  • 兼容性较好(较老版本的浏览器也支持)
  • 不必对服务器端进行配置(或配置相对较少)

基本原理

在网页添加一个<script>元素,再向服务器请求JSON数据。服务器收到请求后,将数据存放在一个指定的回调函数callback()里。

CORS(跨域资源共享)

这种方法允许浏览器向跨源服务器发出XMLHttpRequest请求,从而克服了同源策略的限制。

好处是:

  • 较方便配置
  • 兼容所有请求方式

局限性是:

  • 较老版本的浏览器可能不支持
  • 需要在服务器端配置

基本原理(仅针对简单请求:HEAD、GET、POST)

对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。

下面是一个例子,浏览器发现这次跨源AJAX请求是简单请求,就自动在头信息之中,添加一个Origin字段。

GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

上面的头信息中,Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。

如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段(详见下文),就知道出错了,从而抛出一个错误,被XMLHttpRequestonerror回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。

如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。

Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8

引用

【1】MDN官方文档( https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy )- Author(s): Jesse Ruderman
【2】《跨域资源共享 CORS 详解》[2016-4-12]( http://www.ruanyifeng.com/blog/2016/04/cors.html ) - 作者:阮一峰 - 许可证:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)

— END

本文作者:fly6022
本文链接:https://fly6022.fun/posts/2021-03-07-01/
版权声明:本文采用 署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0) 协议进行许可,转载请注明原出处。