新的瀏覽器緩存策略變更:舍棄性能、確保安全
通常,緩存可以通過存儲(chǔ)數(shù)據(jù)來提高性能,從而可以更快后面相同數(shù)據(jù)的請(qǐng)求。例如,來自網(wǎng)絡(luò)的緩存資源可以避免頻繁的和服務(wù)器交互。緩存計(jì)算結(jié)果可以省去進(jìn)行相同計(jì)算的時(shí)間。
在 Chrome 中,緩存機(jī)制以多種方式使用,HTTP 緩存就是一個(gè)示例。
Chrome 的 HTTP 緩存當(dāng)前的工作方式
從 85 版開始,Chrome 會(huì)使用它們各自的資源URL作為緩存鍵來緩存從網(wǎng)絡(luò)獲取的資源。
下面我們來看幾個(gè)示例:
(1) Cache Key: { https://x.example/doge.png }
用戶訪問了頁面(https://a.example),然后請(qǐng)求了一個(gè)圖像(https://x.example/doge.png)。該圖像是從網(wǎng)絡(luò)請(qǐng)求的,瀏覽器會(huì)使用 https://x.example/doge.png 用作 key 進(jìn)行緩存。
(2) Cache Key: { https://x.example/doge.png }
同一用戶訪問另一個(gè)頁面(https://b.example),這個(gè)頁面請(qǐng)求了相同的圖像(https://x.example/doge.png)。瀏覽器使用圖像 URL 作為 key ,檢查其 HTTP 緩存是否已經(jīng)緩存了此資源。瀏覽器在其緩存中找之前緩存的資源,因此它使用了資源的緩存版本。
(3) Cache Key: { https://x.example/doge.png }
圖像是否從 iframe 中加載都沒有關(guān)系。如果網(wǎng)站 https://c.example 使用 iframe(https://d.example)訪問另一個(gè)網(wǎng)站,并且 iframe 中請(qǐng)求了相同的圖片(https://x.example/doge.png) ,則瀏覽器仍可以從緩存中加載圖片,因?yàn)樗许撁娴木彺?key 均相同。
緩存機(jī)制存在的問題
從性能的角度來看,這種機(jī)制已經(jīng)運(yùn)行了很長時(shí)間了。但是,網(wǎng)站響應(yīng) HTTP 請(qǐng)求所花費(fèi)的時(shí)間可以表明瀏覽器過去曾經(jīng)訪問過相同的資源,這使瀏覽器容易受到安全和隱私的攻擊,比如:
- 檢測用戶是否訪問過特定站點(diǎn):攻擊者可以通過檢查緩存是否具有特定于特定站點(diǎn)或一組站點(diǎn)的資源來檢測用戶的瀏覽歷史記錄。
- 跨站點(diǎn)搜索攻擊:攻擊者可以通過檢查特定網(wǎng)站使用的“無搜索結(jié)果”圖像是否在瀏覽器的緩存中來檢測用戶的搜索結(jié)果中是否包含任意字符串。
- 跨站點(diǎn)跟蹤:緩存可用于存儲(chǔ)類似 cookie 的標(biāo)識(shí)符,作為跨站點(diǎn)跟蹤機(jī)制。
為了減輕這些風(fēng)險(xiǎn),Chrome 將從 Chrome 86 開始對(duì) HTTP 緩存進(jìn)行分區(qū)。
緩存分區(qū)將如何影響 Chrome 的 HTTP 緩存?
通過緩存分區(qū),除了資源 URL 外,還將使用新的 “網(wǎng)絡(luò)隔離密鑰” 來對(duì)緩存的資源進(jìn)行密鑰設(shè)置。網(wǎng)絡(luò)隔離密鑰由頂級(jí)站點(diǎn)和當(dāng)前 frame 中的站點(diǎn)組成。
注意:“站點(diǎn)”使用 “scheme://eTLD+1 ”識(shí)別,因此,如果請(qǐng)求來自不同的頁面,但是它們具有相同的 scheme 和有效的 eTLD+1,則它們將使用相同的緩存分區(qū)。
再次查看前面的示例,以了解緩存分區(qū)如何在不同的上下文中工作:
(1) Cache Key: { https://a.example, https://a.example, https://x.example/doge.png }
用戶訪問 https://a.example 請(qǐng)求圖像(https://x.example/doge.png)。在這種情況下,圖像是從網(wǎng)絡(luò)請(qǐng)求的,并使用由 https://a.example(頂級(jí)站點(diǎn)), https://a.example(當(dāng)前 frame 中的站點(diǎn))和 https://x.example/doge.png(資源URL)組成的元組作為 key 進(jìn)行緩存。(請(qǐng)注意,當(dāng)資源請(qǐng)求來主頁面時(shí),網(wǎng)絡(luò)隔離密鑰中的頂級(jí)站點(diǎn)和當(dāng)前 frame 中的站點(diǎn)是相同的。)
(2) Cache Key: { https://b.example, https://b.example, https://x.example/doge.png }
同一用戶訪問了 https://b.example 請(qǐng)求相同圖片(https://x.example/doge.png)。盡管在上一個(gè)示例中加載了相同的圖像,但是由于密鑰不匹配,因此不會(huì)被緩存命中。
(3) Cache Key: { https://a.example, https://a.example, https://x.example/doge.png }
現(xiàn)在用戶回到了 https://a.example ,但是這次圖像(https://x.example/doge.png)被嵌入到了 iframe 中。在這種情況下,圖片緩存的 key 和直接在主頁面加載的圖片的緩存 key 是相同的,因此可以使用之前緩存的圖片資源。
(4) Cache Key: { https://a.example, https://c.example, https://x.example/doge.png }
這個(gè)例子中,圖像在 https://c.example 的 iframe 中加載,在這種情況下,圖像是從網(wǎng)絡(luò)上下載的,因?yàn)榫彺嬷姓也坏较嗤拿荑€。
(5) Cache Key: { https://a.example, https://c.example, https://x.example/doge.png }
如果域包含子域或端口號(hào)怎么辦?用戶訪問 https://subdomain.a.example ,其中嵌入的 iframe (https://c.example:8080) 請(qǐng)求了圖像的。
由于密鑰是基于 scheme://eTLD+1 創(chuàng)建的,因此將忽略子域和端口號(hào)。所以本次發(fā)生緩存命中。
(6) Cache Key: { https://a.example, https://c.example, https://x.example/doge.png }
如果 iframe 多次嵌套該怎么辦?用戶訪問 https://a.example,其中嵌入了一個(gè) iframe(https://b.example),它又嵌入了另一個(gè) iframe(https://c.example),這個(gè) iframe 最終請(qǐng)求了圖像。
由于密鑰是從 https://a.example 加載資源的頂部 frame 和直接frame (https://c.example)獲取的,因此會(huì)發(fā)生緩存命中。
對(duì)現(xiàn)有網(wǎng)站的影響
這不是一個(gè)重大變化,但可能會(huì)影響某些網(wǎng)頁的性能。
例如,在許多站點(diǎn)上為大量可高度緩存的資源提供服務(wù)的站點(diǎn)(例如字體和流行的腳本)可能會(huì)看到其流量增加。同樣,使用此類服務(wù)的人可能會(huì)越來越依賴于它們。
下面是一些性能指標(biāo)的變化:
- 整體緩存未命中率增加了約 3.6%
- FCP 增加約 0.3%
- 從網(wǎng)絡(luò)加載的字節(jié)的總體比例增加了約 4%
其他瀏覽器的行為
- Chrome: 使用頂級(jí) scheme://eTLD+1 加 frame scheme://eTLD+1
- Safari: 使用頂級(jí) eTLD+1
- Firefox: 計(jì)劃實(shí)施頂級(jí) scheme://eTLD+1 然后也考慮像 Chrome 一樣增加第二個(gè) key






























