HTTP 协议跨域问题

马谦马谦马谦 TCP/IP评论971字数 2655阅读 8 分 51 秒阅读模式

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

一、什么是跨域

1.1 跨域描述

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

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

如:

  1. http://www.a.com/https://www.a.com:协议不同,跨域访问。
  2. http://www.a.comhttp://www.b.com:域名不同,跨域。
  3. http://www.a.com:8080http://www.a.com:8081:端口不同,跨域。

在跨域情况下,浏览器会抛出以下错误信息:

HTTP协议跨域问题-图片1

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

1.2 跨域的解决方案

如果 A(域名https://www.baidu.com) 站希望访问到 B 站的脚本,在 B 站的响应头中加上 Access-Control-Allow-Origin 字段。如:

其中的 https://www.baidu.com 也可以改成*,表示允许所有的站点访问,但可能会产生不安全的因素。

二、测试案例

2.1 准备

为了测试多种环境,准备了一个 iis 服务器和一个装有 nginx 的虚拟机,虚拟机地址 192.168.234.128,本机地址 192.168.123.152 。 hosts 设置了两个域名 winiis.cn 和 vmcentos.cn 分别表示本机 (192.168.123.152) 和虚拟机 (192.168.234.128):

测试页面文件 index.html,代码如下:

代码的主要功能就是发起一个 js 请求,请求站点的文本文件内容。

2.2 开启 iis 服务

同级目录下创建一个 test.txt,写入数据 123456,在 IIS 中配置 web 服务:

HTTP协议跨域问题-图片2

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

HTTP协议跨域问题-图片3

点击按钮会弹框:

HTTP协议跨域问题-图片4

2.3 开启 nginx 服务

拷贝 index.html 和 test.txt 到虚拟机的/data/www/cors 目录下,然后在 nginx 中配置一个虚拟主机:

在浏览器输入 vmcentos.cn 同样也出现上面内容。

2.4 跨域访问

修改本机的 index.html 文件:

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

然后分别点击两个页面的按钮,发现都不会有弹框,按 F12 控制台有以下错误:

HTTP协议跨域问题-图片5

这个错误就是跨域的错误信息,因为本机的域名是 winiis.cn,访问的文件地址为 vmcentos.cn,两者不同源,产生了跨域。

2.5 解决方案

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

HTTP协议跨域问题-图片6

只是当我们通过浏览器访问时,浏览器为了安全会过滤掉这个请求 (注意,拦截是在浏览器做的),抛出错误。要解决这个问题要用到浏览器的 CORS 策略,在服务端响应头中加上 Access-Control-Allow-Origin 字段,字段值设置成允许调用的源站地址。即:

在 nginx 中设置 CORS:

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

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

在 iis 中设置 CORS:

主界面中依次点击 HTTP 响应标头-添加头

HTTP协议跨域问题-图片7

HTTP协议跨域问题-图片8

三、跨域原理

当我们进行跨域访问时,请求头中会加上 originrefer 字段标明该连接的来源 (普通的请求中是没有的),浏览器就会通过这个来判断是否是跨域。例如上面在本机的页面中点击按钮访问 vmcentos.cn/test.txt 时,会加上以下的头部:

HTTP协议跨域问题-图片9

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

HTTP协议跨域问题-图片10

其实所有的跨域操作都是在浏览器中完成的,它收到响应后,会先判断是否为跨域链接,如果跨域再判断 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 字体导致的。

  最后更新:2020-1-29
马谦马谦马谦
  • 本文由 马谦马谦马谦 发表于 2017 年 12 月 16 日 23:03:26
  • 转载请务必保留本文链接:https://www.dyxmq.cn/network/tcpip/http-cors-access-control-allow-origin.html
HTTP/2简介 计算机网络

HTTP/2 简介

一、 HTTP/2 概述 HTTP/2 是 HTTP 协议的第二个大版本,相较于 HTTP/1 而言,HTTP/2 的核心观念是 「构建一个更快、更简单以及更强大」 的 web 应用。 HTTP/2 will make ou...
HTTP协议中的keep-alive机制 计算机网络

HTTP 协议中的 keep-alive 机制

一、长连接和短连接 长连接和短链接的概念: 短连接:传输完数据后连接立刻关闭。 长连接:传输完数据后不会立刻关闭连接,下次传输数据继续复用这个连接。 很容易看出,长连接和短连接的主要区别就是连接完成后...
匿名

发表评论

匿名网友
:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:
确定

拖动滑块以完成验证