微信圖片另存失敗?這得從SNI提及

1、從一個微信Bug提及

問題:在微信Android客戶端,一張七牛CDN上的HTTPS連接的圖片,用微信瀏覽器打開能夠正常訪問,可是,長按圖片保存時,卻提示下載圖片失敗。前端

發現這個問題後,我用了一個簡單的測試用例,很快就定位到問題緣由。nginx

6-pic.jpg
6-pic.jpg

從這個測試用例能夠看出,只有七牛CDN上HTTPS連接的圖片,長按保存纔會失敗。有了這個測試用例,我就猜想問題多是HTTPS證書的緣由。web

因而,我就把這個問題報給了七牛,七牛排查以後,問題果真是HTTPS證書返回不對引發的。那麼,是什麼緣由致使七牛返回的HTTPS證書不對呢?請繼續看下文。瀏覽器

在瞭解問題的本質緣由以前,咱們先來了解一些相關的背景知識。性能優化

2、背景知識

在早期的服務器部署方案中,一臺服務器(或者說一個IP)只會提供一個服務,因此在SSL握手時,服務器端能夠確認客戶端申請的是哪張證書,由於證書只有一張,服務器只要把這張證書發送給客戶端就能夠了。以下圖所示:服務器

1-pic.jpg
1-pic.jpg

一臺物理機,一個IP,一張HTTPS證書,而且提供了惟一的一個服務(站點),因此,無論哪一個客戶端訪問這個服務,服務器都返回惟一的證書。微信

後來,服務器性能提升了,一臺服務器只部署一個服務就有點浪費了,因此就出現了虛擬主機,這樣服務器雖然只有一個,但能夠在每一個虛擬主機上都部署一個服務,這就形成了一個IP會對應多個域名的狀況。解決方案有一些,例如申請泛域名證書,對全部.yourdomain.com域名均可以認證,但若是你有另一個域名.yourdomain.cn,那就不行了。以下圖所示:網絡

2.jpg
2.jpg

在早期的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信息。

3.jpg
3.jpg

最後找微信的人確認,長按保存圖片時,微信確實沒有把host信息傳給後臺,這是微信圖片下載庫的一個bug。

那麼,微信要解決這個問題,必需要等下一個版本發佈了,有沒有其餘的解決方案呢?

七牛給出了一個解決方案,由於咱們的圖片都是存放在域名dn-kdt-img.qbox.me下面的,而這個域名又是七牛本身的,因此七牛就把全部域名*.qbox.me下的全部節點服務器,都配置了惟一的一張HTTPS證書,當客戶端訪問這些節點服務器的時候,服務器只要返回這張惟一的證書就能夠了。以下圖所示:

2-pic.jpg
2-pic.jpg

無論用戶訪問的是哪一個節點服務器,服務器都只返回這張惟一的證書,這樣處理以後,在創建SSL鏈接時,無論客戶端是否發送了host信息給服務器,服務器都能返回正確的證書。

3、心得體會

一、做爲一個前端工程師,瞭解一些運維的知識仍是頗有必要的,由於咱們在作網站性能優化的時候,常常須要用到運維相關的技能及知識。

二、前端是一個很是有挑戰的崗位,可涉及的知識面會很廣,往前看,你能夠了解一些產品,交互方面的知識,這樣能夠跟用戶靠的更近;日後看,你能夠了解一些後臺的知識,這樣在跟後臺提接口要求的時候,能夠溝通更順暢;往上看,你可讓本身知識面更廣,這樣你能夠看問題更加全面,所謂「站得高,望得遠」即是這樣的道理;忘下看,你能夠深刻去了解某一塊專業知識,這樣你能夠成爲這塊領域的專家。

參考文檔:

本文首發於有贊技術博客:tech.youzan.com/sni/

相關文章
相關標籤/搜索