網頁是獨一無二的應用程式平台。以該架構建構的應用程式可立即在任何作業系統上存取,不需要變更程式碼或編譯。使用者每次開啟應用程式時,都會看到最新版本。 這類應用程式可安裝,且離線也能運作,功能強大,只要提供連結就能輕鬆分享。建構網路應用程式,即可在任何地方運作。
由於網路的目標是預設安全無虞,因此安全模式必須非常保守。新增的任何功能都必須安全無虞,以免一般使用者透過網址意外發現。我們將這種安全模式稱為「網頁式磁碟機」。雖然這對許多應用程式來說很棒,而且可以使用內容安全政策和跨來源隔離來提升安全性,但並非適用於所有用途。開發人員需要許多非常重要且功能強大的 API,例如直接通訊端和受控影格,但這些 API 無法確保網路磁碟機的安全。
目前無法在網路上建構這些應用程式。對其他人來說,網路的安全模型可能不夠保守;他們可能不認為伺服器值得信賴,而是偏好以離散版本和簽署的獨立應用程式。因此需要新的高信任度安全模式。隔離網頁應用程式 (IWA) 提供隔離、捆綁、版本化、簽署及可信賴的應用程式模型,以現有網頁平台為基礎建構而成,可供這些開發人員使用。
網路信任度範圍
您可以將網路上的安全性和功能視為一個光譜。

左側的「drive-by web」信任安全模式最低,因為它必須最容易存取,因此對使用者系統的存取權最少。瀏覽器安裝的網頁應用程式信任度較高,且能更深入整合到使用者的系統。一般來說,使用者可以順利在應用程式的免安裝網頁版和瀏覽器安裝版之間切換。
接著是高信任度的隔離網頁應用程式。
這些應用程式的運作方式和外觀更接近原生應用程式,而且可以存取深入的系統整合和強大功能。使用者無法在兩者之間切換,也無法使用 drive-by-web。如果您需要這種安全等級或這些功能,就無法返回。
決定要採用哪種安全模式時,請預設採用信任度最低的安全模式,例如漸進式網頁應用程式。這樣一來,您就能觸及最多使用者,需要自行管理的安全疑慮最少,開發人員和使用者也能享有最大的彈性。
融入安全考量的設計
隔離網頁應用程式可為網頁應用程式提供高信任度的安全模型。不過,如要啟用這項功能,必須重新思考網頁版雲端硬碟對信任的假設。伺服器和 DNS 等核心網路建構區塊不再能明確信任。原本似乎與原生應用程式較相關的攻擊媒介,突然變得重要。因此,如要存取 IWA 提供的新高信任度安全模型,網頁應用程式必須經過封裝、隔離及鎖定。
已包裝
隔離網頁應用程式的網頁和資產無法從即時伺服器提供,也無法像一般網頁應用程式一樣透過網路擷取。如要存取新的高信任度安全模型,網頁應用程式必須將執行所需的所有資源封裝到簽署的 WebBundle 中。簽署的網頁組合會擷取執行網站所需的所有資源,並將這些資源封裝成 .swbn 檔案,然後與完整性區塊串連。這樣一來,使用者就能安全下載整個網頁應用程式,甚至在離線時分享或安裝。
不過,這會造成驗證網站程式碼真偽的問題: TLS 金鑰必須連上網際網路才能運作。IWA 並非使用 TLS 金鑰簽署,而是使用可安全離線保存的金鑰簽署。好消息是,只要將所有製作檔案收集到一個資料夾中,就能將其轉換為 IWA,不必進行太多修改。
產生簽署金鑰
簽署金鑰是 Ed25519 或 ECDSA P-256 金鑰組,私密金鑰用於簽署套件,公開金鑰則用於驗證套件。您可以使用 OpenSSL 產生及加密 Ed25519 或 ECDSA P-256 金鑰:
# Generate an unencrypted Ed25519 key
openssl genpkey -algorithm Ed25519 -out private_key.pem
# or generate an unencrypted ECDSA P-256 key
openssl ecparam -name prime256v1 -genkey -noout -out private_key.pem
# Encrypt the generated key. This will ask for a passphrase, make sure to use a strong one
openssl pkcs8 -in private_key.pem -topk8 -out encrypted_key.pem
# Delete the unencrypted key
rm private_key.pem
簽署金鑰也有次要用途,由於網域可能容易失去控制權 (例如伺服器),因此無法用來識別已安裝的 IWA。而是透過套件的公開金鑰 (屬於簽章的一部分,且與私密金鑰相關聯) 識別 IWA。這是對免安裝網頁運作方式的重大變更,因此 IWA 不會使用 HTTPS,而是採用新的配置:isolated-app://。
建立應用程式套件
取得簽署金鑰後,即可開始將網頁應用程式打包。如要打包並簽署 IWA,可以使用官方 NodeJS 套件 (Go 指令列工具也適用)。首先,請使用 wbn 套件,指向包含所有 IWA 生產檔案的資料夾 (這裡為 dist),將這些檔案包裝成未簽署的套件:
npx wbn --dir dist
這會產生該目錄的未簽署網頁套件至 out.wbn.。產生後,請使用先前建立的加密 Ed25519 或 ECDSA P-256 金鑰,透過 wbn-sign 簽署:
npx wbn-sign -i out.wbn -k encrypted_key.pem -o signed.swbn
這會從名為「signed.swbn」的未簽署網頁軟體包產生已簽署網頁軟體包。簽署後,工具也會輸出網頁軟體包 ID 和其隔離網頁應用程式來源。瀏覽器會根據隔離網頁應用程式來源識別 IWA。
Web Bundle ID: ggx2sheak3vpmm7vmjqnjwuzx3xwot3vdayrlgnvbkq2mp5lg4daaaic
Isolated Web App Origin: isolated-app://ggx2sheak3vpmm7vmjqnjwuzx3xwot3vdayrlgnvbkq2mp5lg4daaaic/
如果您使用 Webpack、Rollup 或支援這些外掛程式的工具 (例如 Vite),可以改用其中一個整合工具外掛程式 (Webpack、Rollup) 包裝這些套件,不必直接呼叫。這麼做會產生簽署的套件組合,做為建構作業的輸出內容。
測試應用程式
您可以透過兩種方式測試 IWA:透過 Chrome 內建的 IWA 開發人員 Proxy 執行開發伺服器,或是安裝已封裝的 IWA。如要這麼做,您必須使用 Chrome 或 ChromeOS 120 以上版本, 啟用 IWA 旗標,然後透過 Chrome 的 Web App Internals 安裝應用程式:
- 啟用
chrome://flags/#enable-isolated-web-app-dev-mode標記 - 前往 Chrome 的「Web App Internals」(網頁應用程式內部) 頁面 (
chrome://web-app-internals),測試 IWA。
進入「網頁應用程式內部」頁面後,您有兩個選擇:Install IWA with Dev
Mode Proxy 或 Install IWA from Signed Web Bundle。
如果透過開發人員模式 Proxy 安裝,您可以將任何網址 (包括從本機開發伺服器執行的網站) 安裝為 IWA,不必進行組合,前提是這些網址符合其他 IWA 安裝規定。安裝完成後,系統會為該網址新增 IWA,並套用正確的安全政策和限制,以及 IWA 專用 API 的存取權。系統會指派隨機 ID。您也可以在這個模式中使用 Chrome 開發人員工具,對應用程式進行偵錯。如果您從已簽署的 Web Bundle 安裝,系統會上傳您已簽署的 IWA 套件,並以使用者下載的形式安裝。
在「Web App Internals」頁面上,您也可以強制檢查透過開發人員模式 Proxy 或簽署的網頁套件安裝的任何應用程式更新,以測試更新程序。
已隔離建構作業
信任是隔離網頁應用程式的關鍵。首先是瞭解他們的運作方式。使用者對應用程式的功能和應具備的能力有不同的心理模型,具體取決於應用程式是在瀏覽器中執行,還是在獨立視窗中執行。一般來說,使用者會認為獨立應用程式的存取權較多,功能也更強大。由於 IWA 可以存取高信任度 API,因此必須在獨立視窗中執行,才能符合這個心理模型。這會將這些分頁與瀏覽器在視覺上區隔開來。但這不僅僅是視覺上的區隔。
與瀏覽器內網站不同,獨立網頁應用程式採用不同的通訊協定 (isolated-app 與 http 或 https)。這表示即使是由同一間公司建構,每個 IWA 都會與瀏覽器內執行的網站完全區隔,這都要歸功於同源政策。IWA 儲存空間也會彼此獨立。這兩項措施可確保跨來源內容不會在不同 IWA 之間,或是在 IWA 與使用者的正常瀏覽環境之間洩漏。
但如果 IWA 在安裝後可以下載及執行任意程式碼,那麼無論是隔離還是將網站程式碼與簽章一併封裝,都無法建立信任關係。為確保這點,同時允許 IWA 連線至其他網站以取得內容,IWA 會強制執行嚴格的內容安全政策:
- 只允許來自套件的 JavaScript,但允許執行 Wasm,無論來源為何。(
script-src) - 允許 JavaScript 從安全、非本機主機的跨來源網域擷取資料、連線至 WebSocket 和 WebTransport 端點,以及 blob 和 data 網址 (
connect-src) - 控管 DOM 操控函式的使用方式 (
require-trusted-types-for),防範 DOM 跨網站指令碼植入 (XSS) 攻擊 - 允許來自任何 HTTPS 網域的影格、圖片、音訊和影片
(
frame-src、img-src、media-src) - 允許來自套件和 Blob 的字型
(
font-src) - 允許來自套件的內嵌 CSS 或 CSS
(
style-src) <object>、<embed>和<base>元素無法使用 (object-src和base-uri)- 只允許來自套裝組合的資源,用於任何其他 CSP 涵蓋的要求 (
default-src)
Content-Security-Policy: script-src 'self' 'wasm-unsafe-eval';
connect-src 'self' https: wss: blob: data:;
require-trusted-types-for 'script';
frame-src 'self' https: blob: data:;
img-src 'self' https: blob: data:;
media-src 'self' https: blob: data:;
font-src 'self' blob: data:;
style-src 'self' 'unsafe-inline';
object-src 'none';
base-uri 'none';
default-src 'self';
這些 CSP 不足以完全防範潛在的惡意第三方程式碼。此外,IWA 也跨來源隔離,可設定標頭,減少第三方資源對 IWA 的影響:
- 只允許來自套件的資源,或明確標示為支援 CORS 的跨源資源,並設定跨源資源政策 (CORP) 標頭或
crossorigin屬性。(Cross-Origin-Embedder-Policy) - 禁止無 CORS 的跨源要求
(
Cross-Origin-Resource-Policy) - 將瀏覽內容與跨來源文件進行程序隔離,防止 window.opener 參照和全域物件存取 (
Cross-Origin-Opener-Policy) - 禁止在框架或 iframe 中嵌入網站 (CSP、
frame-ancestors)
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Resource-Policy: same-origin
Content-Security-Policy: frame-ancestors 'self'
即使有這些限制,IWA 仍可防範另一種潛在攻擊:序列中斷攻擊。如果惡意第三方內容嘗試以非預期的方式導向某個頁面 (例如直接導向內部設定頁面),藉此製造混淆不清且可能遭到濫用的使用者體驗,就會發生序列中斷攻擊。IWA 會禁止外部網站的任意深層連結,只允許透過明確定義的進入點 (例如 start_url、通訊協定處理常式、分享目標或啟動處理常式) 開啟應用程式,藉此防止這類情況發生。
已鎖定
封裝和隔離機制可確保允許執行的內容及其來源,但網頁權限的動態特性表示,單靠這兩項機制無法確保網頁應用程式只使用所需的權限。由於不同功能有不同的安全性考量,使用者或管理員會想稽核 IWA 可能使用的權限,就像他們在安裝或更新應用程式前,可以對 Android 和 iOS 等其他原生應用程式執行稽核一樣。
為此,隔離網頁應用程式預設會封鎖所有權限要求。
開發人員接著可以在網頁應用程式資訊清單中新增 permissions_policy 欄位,選擇加入所需的權限。這個欄位包含 權限政策指令和權限政策允許清單的鍵/值配對,適用於 IWA 或任何子框架 (例如受控框架或 iframe) 可能要求的每項權限。在此新增權限不會自動授予權限,而是讓使用者在要求該功能時,可以要求取得權限。
假設您要建構車隊追蹤 IWA。您可能需要 IWA 才能要求使用者位置,內嵌地圖也需要要求位置。您可能也希望嵌入的網站能夠全螢幕顯示,為使用者提供沉浸式體驗。如要這麼做,請在網頁應用程式資訊清單中設定下列權限政策:
"permissions_policy": {
"geolocation": [ "self", "https://map.example.com" ],
"fullscreen": [ "*" ]
}
由於 WebBundle 也可以指定「權限政策」 標頭,因此系統只會允許兩者都宣告的權限,且只允許兩者都列入允許清單的來源。
已命名和版本化
一般網頁應用程式會依賴網域名稱向使用者識別自己,並可透過變更該網域提供的程式碼進行更新。但由於獨立網頁應用程式有安全限制,因此身分和更新必須以不同方式處理。與漸進式網頁應用程式類似,隔離網頁應用程式也需要 Web App Manifest 檔案,才能向使用者識別。
網頁應用程式資訊清單
隔離網頁應用程式與 PWA 的網頁應用程式資訊清單,共用相同的主要資訊清單屬性,但有些微差異。舉例來說,display 的運作方式略有不同;browser 和 minimal-ui 都會強制進入 minimal-ui 顯示畫面,而 fullscreen 和 standalone 則會強制進入 standalone 顯示畫面 (其他 display_override 選項則會正常運作)。此外,還應加入另外兩個欄位:version 和 update_manifest_url:
version:隔離網頁應用程式必須提供這項資訊。由一或多個以半形句號 (.) 分隔的整數組成的字串。版本可以是簡單的1、2、3等,也可以是複雜的 SemVer (1.2.3)。版本號碼應符合^(\d+.?)*\d$的規則運算式。update_manifest_url:選填,但建議填寫這個欄位,指向可擷取網頁應用程式更新資訊清單的 HTTPS 網址 (或用於測試的localhost)。
隔離的網頁應用程式的基本網頁應用程式資訊清單可能如下所示:
{
"name": "IWA Kitchen Sink",
"version": "0.1.0",
"update_manifest_url": "https://example.com/updates.json",
"start_url": "/",
"icons": [
{
"src": "/images/icon.png",
"type": "image/png",
"sizes": "512x512",
"purpose": "any"
},
{
"src": "/images/icon-mask.png",
"type": "image/png",
"sizes": "512x512",
"purpose": "maskable"
}
]
}
網頁應用程式更新資訊清單
網頁應用程式更新資訊清單是 JSON 檔案,用於說明指定網頁應用程式的每個版本。JSON 物件包含一個必要欄位 version,這是包含 version、src 和 channels 的物件清單:
version:應用程式的版本號碼,與 Web 應用程式資訊清單的version欄位相同src- 指向該版本代管套件的 HTTPS 網址 (或用於測試的localhost),即.swbn檔案。相對網址是相對於 Web 應用程式更新資訊清單檔案。channels- 字串清單,用來識別這個版本所屬的更新管道。系統會使用特殊的default管道,說明在未選取其他管道時使用的主要管道。
你也可以加入 channels 欄位,也就是頻道 ID 物件,並為每個 ID 提供選用的 name 屬性,以提供可供使用者辨識的名稱 (包括 default 頻道)。如果管道不含 name 屬性,或未納入 channels 物件,系統會使用管道 ID 做為名稱。
極簡更新資訊清單可能如下所示:
{
"versions": [
{
"version": "5.2.17",
"src": "https://cdn.example.com/app-package-5.2.17.swbn",
"channels": ["next", "5-lts", "default"]
},
{
"version": "5.3.0",
"src": "v5.3.0/package.swbn",
"channels": ["next", "default"]
},
{
"version": "5.3.1",
"src": "v5.3.1/package.swbn",
"channels": ["next"]
},
],
"channels": {
"default": {
"name": "Stable"
},
"5-lts": {
"name": "5.x Long-term Stable"
}
}
}
在這個範例中,有三個管道:標示為 Stable 的 default、標示為 5.x Long-term Stable 的 5-lts,以及標示為 next 的 next。如果使用者採用 5-lts 管道,就會取得 5.2.17 版本;如果採用 default 管道,就會取得 5.3.0 版本;如果採用 next 管道,就會取得 5.3.1 版本。
網頁應用程式更新資訊清單可代管於任何伺服器。系統每 4 到 6 小時會檢查一次更新。
由管理員控管
在初期,只有管理員能透過管理面板,在 Chrome Enterprise 管理的 Chromebook 上安裝隔離網頁應用程式。
如要開始使用,請前往管理面板,然後依序點選「裝置」>「Chrome」>「應用程式和擴充功能」>「使用者和瀏覽器」。您可以在這個分頁中,為整個機構的使用者新增 Chrome 線上應用程式商店、Google Play 和網路上的應用程式和擴充功能。如要新增項目,請開啟畫面右下角的黃色浮動新增 (+) 按鈕,然後選取要新增的項目類型。
開啟後,您會看到一個正方形內的正方形圖示,標示為「新增隔離的網頁應用程式」。點按該圖示會開啟模式,讓您將 IWA 新增至機構單位。如要這麼做,您需要兩項資訊:IWA 的網頁軟體包 ID (從應用程式的公開金鑰產生,並在應用程式完成軟體包化和簽署後顯示),以及 IWA 的網頁應用程式更新資訊清單網址。安裝完成後,您可以使用管理面板的標準選項組合來管理擴充功能:
- 安裝政策:您希望如何安裝 IWA,包括強制安裝、強制安裝並固定至 ChromeOS 應用程式架,或禁止安裝。
- 登入時啟動:您希望 IWA 的啟動方式,可以允許使用者手動啟動、強制在使用者登入時啟動 IWA,但允許關閉,或強制在使用者登入時啟動 IWA,並禁止關閉。
儲存後,下次對該 OU 中的 Chromebook 套用政策更新時,系統就會安裝應用程式。安裝後,使用者裝置每隔 4 到 6 小時就會檢查 Web 應用程式更新資訊清單是否有更新。
除了強制安裝 IWA,您也可以自動授予某些權限,方式與其他網頁應用程式類似。如要這麼做,請依序前往「裝置」>「Chrome」>「網路功能」,然後按一下「新增來源」按鈕。在 Origin / site pattern field 中,貼上 IWA 的網頁軟體包 ID (isolated-app:// 會自動新增為其通訊協定)。您可以在該處為不同 API 設定存取層級 (允許/封鎖/未設定),包括視窗管理、本機字型管理和螢幕監控 API。如果 API 需要管理員額外啟用 (例如強制螢幕監控 API),系統會彈出額外對話方塊,請確認您的選取項目。完成後,請儲存變更,使用者即可開始使用 IWA!
使用擴充功能
雖然隔離網頁應用程式無法直接使用擴充功能,但您可以將擁有的擴充功能連結至隔離網頁應用程式。如要這麼做,請編輯擴充功能的資訊清單檔案。資訊清單的 externally_connectable 區段會定義擴充功能可與哪些外部網頁或其他 Chrome 擴充功能互動。在 externally_connectable 的 matches 欄位中新增 IWA 的來源 (請務必加入 isolated-app:// 配置):
{
"externally_connectable": {
"matches": ["isolated-app://79990854-bc9f-4319-a6f3-47686e54ed29/*"]
}
}
雖然這可讓擴充功能在獨立網頁應用程式中執行,但無法將內容注入其中,您只能在擴充功能和 IWA 之間傳遞訊息。