HTTP协议(二):HTTP跨域分析

马谦马谦马谦 2017年12月16日23:03:26 发表评论
文章最后编辑于:2017-12-17 21:12:25

使用CDN的时候遇到了跨域问题,在网上找解决方法都是说在nginx里面加上请求头,然而设置了请求头后发现还是没有解决问题。所以为了解决问题,并且彻底弄清楚这其中的原理,花了半天时间仔细分析了一下。

一、什么是跨域

跨域是一种安全机制,使浏览器只能在页面内执行同源站点的脚本文件。

所谓同源指的是协议、域名和端口都相同的地址,三者任意条件不满足则视为跨域:

  • https://www.a.com/https://www.a.com :协议不同,跨域。
  • https://www.a.comhttps://www.b.com :域名不同,跨域。
  • https://www.a.com:8080https://www.a.com:8081 :端口不同,跨域。

在跨域情况下,浏览器往往会抛出以下类似错误:

跨域往往会给用户带来太多的不安全因素,所以浏览器出于安全考虑是禁止跨域访问的。

二、跨域的案例

2.1 准备

为了测试多种环境,准备了一个iis服务器和一个装有nginx的虚拟机,虚拟机地址192.168.234.128,本机地址192.168.123.152

hosts设置了两个域名winiis.cnvmcentos.cn分别表示本机和虚拟机:

一个测试页面文件index.html

代码的含义是点击页面中的按钮,会显示页面目录下test.txt文件中的数据内容。

这时需要在页面的同级目录下创建一个test.txt,写入数据123456,创建成功后开启web服务测试一下是否能正常显示。

2.2 开启iis服务

先在本机下使用iis开启一个web服务,监听本地的80端口:

HTTP协议(二):HTTP跨域分析

开启成功后,在浏览器输入winiis.cn会出现以下页面:

HTTP协议(二):HTTP跨域分析

点击按钮会显示test.txt中的数据:

HTTP协议(二):HTTP跨域分析

2.3 开启nginx服务

nginx中也开启一个web服务,拷贝index.htmltest.txt到虚拟机的/data/www/cors目录下,配置一个虚拟主机跑起来:

配置成功后在浏览器输入vmcentos.cn同样也出现上面内容。

2.4 跨域访问

上面的两个web服务,由于都是访问的同源地址中的文件,所以访问不会有什么问题,能正常弹出信息。但是如果把两个服务的请求文件互换以下,让本机的web页面请求虚拟机中的test.txt,同时也让虚拟机中的web页面请求本机test.txt,这时候就会出问题了。

修改本机的index.html文件:

修改虚拟机中的index.html文件:

然后再次打开两个页面,点击按钮,这时候就不会有弹框了,同时按F12控制台会出现以下错误:

HTTP协议(二):HTTP跨域分析

此时就出现了跨域问题,因为本机的域名是winiis.cn,访问的文件地址为vmcentos.cn/test.txt,两者不同源,出现了跨域,所以浏览器报错。虚拟机中的web服务也是如此。

 

三、解决方法

上面当我们访问test.txt时它不可访问的,准确的说并不是不可访问,而是跨域的时候不能访问,当我们在浏览器输入https://vmcentos.cn/test.txt直接访问是可以访问的:

HTTP协议(二):HTTP跨域分析

只是当我们通过浏览器访问时,浏览器为了安全会过滤掉这个请求,抛出错误。要解决这个问题要用到浏览器的CORS策略,只需要在服务端的响应头中加上Access-Control-Allow-Origin字段即可。字段值为我们允许的来源地址,例如想要在winiis.cn中访问vmcentos.cn/test.txt,需要在vmetnos.cn的服务端中设置响应头:

3.1 nginx中设置CORS

nginx设置CORS只要在location代码块中添加以下内容即可,后面是允许的源站地址:

也可以把https://winiis.cn写成*表示允许所有来源的跨域访问,但一般不建议这样做,会引起安全问题。

3.2 在iis中设置CORS

主界面中依次点击HTTP响应标头-添加头,然后设置就可以了:

HTTP协议(二):HTTP跨域分析HTTP协议(二):HTTP跨域分析

当设置完成之后,两个页面就又能正常显示数据信息了。

四、原理

当我们进行跨域访问时,请求头中会加上originrefer字段标明该连接的来源(普通的请求中是没有的),浏览器就会通过这个来判断是否是跨域。

例如上面在本机的页面中点击按钮访问vmcentos.cn/test.txt时,头部信息为:

HTTP协议(二):HTTP跨域分析

如果服务端设置了CORS策略,当服务端收到请求后,添加上Access-Control-Allow-Origin给浏览器返回。在这个过程里,服务端并不会进行跨域判断,只会给予响应然后加上相应的头部,不管是不是跨域请求,服务端都会返回数据。这一点可以从下图中看出,虽然跨域了,但是服务端依旧返回了123456

HTTP协议(二):HTTP跨域分析

其实所有的跨域操作都是在浏览器中完成的,它收到响应后,会先判断是否为跨域链接,如果跨域再判断Access-Control-Allow-Origin字段是否满足条件,满足就正常运行,不满足就会抛出错误,不加载资源。

五、跨域问题的出现时机

并不是所有页面内不同源的文件就会出现跨域问题,像图片文件这种使用<img>标签引用的就不会出现这种情况。会引起跨域问题的情形为:

  • Invocations of the XMLHttpRequest or Fetch APIs in a cross-site manner, as discussed above.
  • Web Fonts (for cross-domain font usage in @font-face within CSS), so that servers can deploy TrueType fonts that can only be cross-site loaded and used by web sites that are permitted to do so.
  • WebGL textures.
  • Images/video frames drawn to a canvas using drawImage.
  • Stylesheets (for CSSOM access).
  • Scripts (for unmuted exceptions).

这里主要是涉及到了一些XMLHttpRequest请求、网页字体以及脚本文件等等,它们在进行不同源访问时会导致跨域,而我们经常使用CDN的时候都会出现跨域问题也就是因为网页内引用了某些css字体导致的。

本文共执行63次查询,耗时0.343秒!
马谦马谦马谦

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: