问题:在微信Android客户端,一张七牛CDN上的HTTPS连接的图片,用微信浏览器打开能够正常访问,可是,长按图片保存时,却提示下载图片失败。前端
发现这个问题后,我用了一个简单的测试用例,很快就定位到问题缘由。nginx
从这个测试用例能够看出,只有七牛CDN上HTTPS连接的图片,长按保存才会失败。有了这个测试用例,我就猜想问题多是HTTPS证书的缘由。web
因而,我就把这个问题报给了七牛,七牛排查以后,问题果真是HTTPS证书返回不对引发的。那么,是什么缘由致使七牛返回的HTTPS证书不对呢?请继续看下文。浏览器
在了解问题的本质缘由以前,咱们先来了解一些相关的背景知识。性能优化
在早期的服务器部署方案中,一台服务器(或者说一个IP)只会提供一个服务,因此在SSL握手时,服务器端能够确认客户端申请的是哪张证书,由于证书只有一张,服务器只要把这张证书发送给客户端就能够了。以下图所示:服务器
一台物理机,一个IP,一张HTTPS证书,而且提供了惟一的一个服务(站点),因此,无论哪一个客户端访问这个服务,服务器都返回惟一的证书。微信
后来,服务器性能提升了,一台服务器只部署一个服务就有点浪费了,因此就出现了虚拟主机,这样服务器虽然只有一个,但能够在每一个虚拟主机上都部署一个服务,这就形成了一个IP会对应多个域名的状况。解决方案有一些,例如申请泛域名证书,对全部.yourdomain.com域名均可以认证,但若是你有另一个域名.yourdomain.cn,那就不行了。以下图所示:网络
在早期的HTTPS协议中,当客户端发起SSL握手时,客户端并不会将host信息带过来,因此服务器就不知道客户端访问的是哪一个域名服务,服务器也就不知道把哪张证书返回给客户端了,出现这种状况时,服务器一般是把默认的一张证书返回给客户端。前端工程师
最后咱们得出的问题关键是:运维
客户端发起SSL握手时,缺乏Host信息。
因此,那些制定网络协议的人,又提出了SNI。
SNI(Server Name Indication)定义在RFC 4366,是一项用于改善SSL/TLS的技术,在SSLv3/TLSv1中被启用。它容许客户端在发起SSL握手请求时(具体说来,是客户端发出SSL请求中的ClientHello阶段),就提交请求的Host信息,使得服务器可以切换到正确的域并返回相应的证书。
检查浏览器是否支持SNI:sni.velox.ch/
另外,不一样的是,在HTTP协议中,客户端发起一个网络请求,客户端都会把主机头host信息放在request header中传给后台,这样服务器就知道客户端访问的是哪一个域名,服务器只要把请求转向相应的服务就能够了。例以下图所示的一个请求,咱们能够看到request header中,带有host信息。
最后找微信的人确认,长按保存图片时,微信确实没有把host信息传给后台,这是微信图片下载库的一个bug。
那么,微信要解决这个问题,必需要等下一个版本发布了,有没有其余的解决方案呢?
七牛给出了一个解决方案,由于咱们的图片都是存放在域名dn-kdt-img.qbox.me下面的,而这个域名又是七牛本身的,因此七牛就把全部域名*.qbox.me下的全部节点服务器,都配置了惟一的一张HTTPS证书,当客户端访问这些节点服务器的时候,服务器只要返回这张惟一的证书就能够了。以下图所示:
无论用户访问的是哪一个节点服务器,服务器都只返回这张惟一的证书,这样处理以后,在创建SSL链接时,无论客户端是否发送了host信息给服务器,服务器都能返回正确的证书。
一、做为一个前端工程师,了解一些运维的知识仍是颇有必要的,由于咱们在作网站性能优化的时候,常常须要用到运维相关的技能及知识。
二、前端是一个很是有挑战的岗位,可涉及的知识面会很广,往前看,你能够了解一些产品,交互方面的知识,这样能够跟用户靠的更近;日后看,你能够了解一些后台的知识,这样在跟后台提接口要求的时候,能够沟通更顺畅;往上看,你可让本身知识面更广,这样你能够看问题更加全面,所谓“站得高,望得远”即是这样的道理;忘下看,你能够深刻去了解某一块专业知识,这样你能够成为这块领域的专家。
参考文档:
本文首发于有赞技术博客:tech.youzan.com/sni/