低成本打造一個帶寬無限的網站 —— No.5 免費空間的挖掘

突破限制

由於 SW 非常強大,因此使用條件也是非常嚴格的,以免被惡意使用。

例如 SW 必須在 HTTPS 站點上使用。這本是件好事,徹底杜絕了中間人的隱患,但現在卻成了一道門檻。

同時,這還引發了另一個問題:由於 HTTPS 站點是禁止讀取 HTTP 數據的,因此我們的節點也必須是 HTTPS 站點!

此外 SW 也得遵守同源策略。如果要讀取第三方站點的數據,目標響應頭裏還得有 Access-Control-Allow-Origin: * 字段 —— 這對於免費空間來說,是個不小的要求。

免費空間,要同時滿足上述兩個條件,確實有些苛刻。好在 SW 能和頁面交互,因此在代理網頁資源時,可以往其中插入一個輔助腳本,這樣就能把任務交給頁面來實現。畢竟頁面裏有豐富的 DOM 功能,可玩出各種奇技淫巧。

頁面代理

對於 不支持 ACAO、但支持 HTTPS 的站點,可通過頁面代理實現 CORS。

我們通過 iframe 引入目標站點下的一個代理頁面,由它來讀取數據,然後將結果 postMessage 給父頁面:

若是追求更高性能的話,還可通過 MessageChannel 直接從 iframe 傳到 SW 裏,減少一次消息中轉:

只要目標站點能部署 html 資源,就可以用這個方案,讀取站點下任意類型的資源!


需注意的是,該方案依賴頁面。假如用戶關閉了所有頁面,然後通過地址欄訪問資源 —— 這時 SW 雖能攔截請求,但由於沒有可交互的頁面,因此無法使用該方案。

不過,有個簡單的辦法可以解決這個問題:我們讓 SW 先返回一個臨時的過渡頁面,用它來配合內容加載;完成後頁面自動刷新,這時 SW 就能給出真正的內容了!

JSONP

對於上述情況,還有種不依賴頁面的辦法 —— 我們將資源打包在腳本文件裏,通過 JSONP 的方式直接在 SW 中加載。

當然這種方案缺陷十分明顯:腳本是文本格式的,編碼二進制資源會增加不少體積。

此外,Worker 中加載腳本的函數 importScripts 是同步阻塞的,因此會對程序帶來很大影響。除非使用 Sub Worker(在 Worker 中嵌套 Worker),但目前很多瀏覽器包括 Chrome 都不支持,所以暫不考慮。

混合內容

對於 不支持 HTTPS、但支持 ACAO 的站點,這時就需要利用 混合內容Mixed Content)機制了。

雖然瀏覽器原則上不允許 HTTPS 頁面引用 HTTP 資源,但對於風險較低的資源,例如圖片、多媒體,仍然是允許的!

因此,我們可將原始數據作爲像素,打包在圖片裏。頁面通過設有 crossOrigin 屬性的 Image 加載圖片,然後繪製到 canvas 上,這樣就能讀取像素,從而得到原始數據了!

演示:https://www.etherdream.com/FunnyScript/jszip/decode.html

關於數據編碼成圖片的細節,可參考《利用 canvas 實現數據壓縮》。不過和文中不同的是,如今我們通過本地工具編碼圖片,因此最終結果還可以用 PNGoutzopflipng 等工具進行強力優化。

當然,數據打包成圖片後,體積不可避免會有所增加。但反正帶寬是免費的,有總比沒有好:)


不過,踩混合內容的黃線,也是有一定代價的。例如 Chrome 瀏覽器,界面上的證書圖標不再是綠色了,並且控制檯裏也會出現告警:

對於這個問題,倒是有個簡單的緩解策略:假如當前開着多個頁面(Tab)的話,我們可以讓 SW 選一個不可見的,由它來加載資源 —— 這樣即使界面有變化,用戶也不會立即看見了:)

Flash 代理

對於既不支持 ACAO 又不支持 HTTPS 的破站點,只能用同樣破舊的東西來配它 —— Flash。

儘管瀏覽器並不允許 HTTPS 頁面加載 HTTP Flash,但我們可以 先加載一個 HTTPS Flash 作爲跳板,然後通過它來加載 HTTP 的資源

因爲插件內部是不受瀏覽器管控的,所以就能利用 Flash 寬鬆的限制,繞過混合內容策略!

只要目標站點支持 xml 資源(用於存放 cross domain xml),我們就能讀取該站點下任意類型的資源!


退一步,即使目標站點不支持 xml 也沒關係,能支持 swf 文件也可以。我們用這個 swf 作爲目標站點的代理,這樣就解決「網絡通信」的同源策略了。

同時,再通過 AS 腳本開放自身權限:

Security.allowDomain('*');

這樣,就能解決「模塊交互」的同源策略了。

這裏用了兩個 swf 做代理 —— 前者規避混合內容,後者規避同源策略,是不是很巧妙:)

有了這個辦法,那些能上傳 swf 的論壇,我們就能讀取和它同站點的圖片附件了!

不過比較尷尬的是,如今主流瀏覽器都已禁用 Flash,當初寫的這些「奇技淫巧」也沒什麼卵用了。。。

總結

HTTPS ACAO 獲取方式 信息載荷類型 依賴頁面 主要缺陷
fetch() * × -
× 頁面代理 * (html) 額外嵌入一個頁面
× JSONP js × Worker 中會阻塞
× 圖片像素 image 混合內容界面警告
× × Flash 代理 * (xml 或 swf) 很多瀏覽器已禁用

這裏我們只是從 HTTPS 和 ACAO 兩個條件進行探討。現實中,當然還有更復雜的情況。

例如,一些圖牀同時支持 HTTPS 和 ACAO,但只能上傳圖片格式。對於這種情況,其實不依賴頁面也是可以加載的 —— 我們可以直接在 SW 中 fetch 圖片,然後用 JS 版的圖像解碼庫,還原出像素裏的數據。

更進一步,我們還可以檢測圖牀是否會修改上傳的原始文件。如果不修改的話,我們可以把數據藏在圖片輔助信息裏,甚至直接附加在文件末尾,這樣直接截取即可,連解碼都不需要了!

總之,只要發揮想象,很多網站都可以利用起來,在我們寬帶緊張的情況下,充當免費的後備節點:)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章