使用權限政策控管瀏覽器功能

管理網頁和網頁上的第三方 iframe 的瀏覽器功能存取權。

Kevin K. Lee
Kevin K. Lee

權限政策 (舊稱「功能政策」) 可讓開發人員宣告一組政策供瀏覽器強制執行,藉此控管網頁、其 iframe 和子資源可用的瀏覽器功能。這些政策會套用至回應標頭來源清單中提供的來源。來源清單可包含相同來源和/或跨來源,可讓開發人員控管第一方和第三方對瀏覽器功能的存取權。

使用者必須最終決定允許存取更強大的功能,也必須接受提示,提供明確權限。

權限政策可讓頂層網站定義自身和第三方意圖使用的功能,並免除使用者決定功能存取權要求是否合法的負擔。舉例來說,如果開發人員使用權限政策封鎖所有第三方的地理位置功能,就能確保沒有第三方會取得使用者的地理位置。

權限政策異動

權限政策先前稱為「功能政策」。主要概念仍維持不變,但名稱上有一些重要異動。

結構化欄位的使用方式

結構化欄位提供一組常見的資料結構,用於標準化 HTTP 標頭欄位值的剖析和序列化。如要進一步瞭解結構化欄位,請參閱 Fastly 的網誌文章「Improving HTTP with structured header fields」。

  geolocation 'self' https://example.com; camera 'none'

使用功能政策之前。

新增
  geolocation=(self "https://example.com"), camera=()

新增權限政策。

使用 iframe allow 屬性合併標頭

透過「功能政策」,您可以將功能新增至跨來源框架,方法是將來源新增至標頭來源清單,或是在 iframe 標記中新增 allow 屬性。在權限政策中,如果您在來源清單中加入跨來源框架,該來源的 iframe 標記必須包含 allow 屬性。如果回應中沒有「Permissions Policy」標頭,系統會將來源清單的預設值視為 *。將 allow 屬性新增至 iframe,即可存取該功能。

因此,我們建議開發人員在回應中明確設定權限政策標頭,這樣即使有 allow,跨來源 iframe 也不得存取這項功能。

在 Chrome 88 之後,您仍可使用功能政策,但這項政策會做為權限政策的別名。除了語法之外,邏輯並無差異。如果同時使用權限政策標頭和功能政策標頭,Permissions-Policy 標頭的優先順序會較高,並會覆寫 Feature-Policy 標頭提供的值。

如何使用權限政策?

快速總覽

在深入探討前,我們先快速回顧一下:身為網站擁有者的常見情況,並想控管網站和第三方程式碼使用瀏覽器功能的方式。

  • 您的網站為 https://your-site.example
  • 你的網站嵌入來自同來源的 iframe (https://your-site.example)。
  • 你的網站嵌入了你所信任的 https://trusted-site.example 的 iframe。
  • 您的網站也會顯示由 https://ad.example 放送的廣告。
  • 您只需允許網站和信任的網站地理位置,而不允許廣告刊登。

在這種情況下,請使用下列標頭:

Permissions-Policy: geolocation=(self "https://trusted-site.example")

並明確將 allow 屬性設為信任網站的 iframe 代碼:

<iframe src="https://trusted-site.example" allow="geolocation">

權限政策使用方式簡介。

在這個範例中,標頭來源清單只允許您的網站 (self) 和 trusted-site.example 使用地理位置功能。ad.example 不得使用地理位置資訊。

  1. 您的網站 (your-site.example) 已取得使用者同意,可以使用地理位置功能。
  2. 同源 iframe (your-site.example) 可使用這項功能,但不必使用 allow 屬性。
  3. 如果 iframe 是從未加入來源清單的不同子網域 (subdomain.your-site-example) 供應,且 iframe 代碼上已設定 allow 屬性,就會遭到封鎖,無法使用這項功能。系統會將不同的子網域視為相同網站,但屬於跨來源。
  4. 跨來源 iframe (trusted-site.example) 已新增至來源清單,且在 iframe 標記上設有 allow 屬性,因此可使用這項功能。
  5. 如果跨來源 iframe (trusted-site.example) 新增至來源清單,但沒有 allow 屬性,就會遭到封鎖,無法使用這項功能。
  6. 未加入來源清單的跨來源 iframe (ad.example) 會遭到封鎖,無法使用這項功能,即使 iframe 代碼中包含 allow 屬性也一樣。

Permissions-Policy HTTP 回應標頭

使用者提出要求,伺服器會回應權限政策標頭,然後瀏覽器會根據該標頭授予存取權。

Permissions-Policy: <feature>=(<token>|<origin(s)>)

在伺服器回應中使用 Permissions-Policy 標頭,設定功能的許可來源。標頭值可採用符記和來源字串的組合。可用的權杖* (所有來源) 和 self (同源)。

如果標頭適用於多個功能,請使用半形逗號分隔各個功能。如果您列出多個來源,請以空格分隔來源清單中的每個來源。如果標頭列出的是跨來源要求的來源,iframe 代碼必須包含 allow 屬性。

以下為部分鍵/值組合範例:

  • 語法:[FEATURE]=*
    • 套用至所有來源的政策
    • 範例:geolocation=*
  • 語法:[FEATURE]=(self)
    • 套用至相同來源的政策
    • 範例:geolocation=(self)
  • 語法:[FEATURE]=(self [ORIGIN(s)])
    • 政策會套用至相同來源與指定來源
    • 範例:geolocation=(self "https://a.example" "https://b.example")
    • selfhttps://your-site.example 的簡寫
  • 語法:[FEATURE]=([ORIGIN(s)])
    • 政策套用至相同來源和指定來源
    • 範例:geolocation=("https://your-site.example" "https://a.example" "https://b.example")
    • 使用這個語法時,其中一個來源應為嵌入程式的來源。此外,如果嵌入網頁本身未獲得權限,即使將 iframe 加入來源清單,該頁面嵌入的 iframe 也會遭到封鎖,這是因為這類 iframe 會委派權限。您也可以使用 self 符記。
  • 語法:[FEATURE]=()
    • 所有來源都無法使用這項功能
    • 範例:geolocation=()

不同的子網域和路徑

不同的子網域 (例如 https://your-site.examplehttps://subdomain.your-site.example) 會視為相同網站但跨來源。因此,在來源清單中新增子網域,並不會允許存取同一個網站的其他子網域。每個要使用這項功能的嵌入子網域都必須分別新增至來源清單。舉例來說,如果只有同源網站可以存取使用者的瀏覽主題,且使用標頭 Permissions-Policy: browsing-topics=(self) 存取,則同一個網站 https://subdomain.your-site.example 的不同子網域中的 iframe 就無法存取這些主題。

不同的路徑 (例如 https://your-site.examplehttps://your-site.example/embed) 會視為同源,且不同的路徑不必列在來源清單中。

iframe allow 屬性

iframe 設定

如要跨來源使用,iframe 需要在標記中加入 allow 屬性,才能存取這項功能。

語法:<iframe src="[ORIGIN]" allow="[FEATURE] <'src' | [ORIGIN(s)]"></iframe>

例如:

<iframe src="https://trusted-site.example" allow="geolocation">

處理 iframe 瀏覽作業

iframe 導覽設定

根據預設,如果 iframe 導向至其他來源,政策就不會套用至 iframe 導向的來源。只要在 allow 屬性中列出 iframe 前往的來源,系統就會將先前 iframe 套用的權限政策套用至 iframe 前往的來源。

<iframe src="https://trusted-site.example" allow="geolocation https://trusted-site.example https://trusted-navigated-site.example">

如要查看實際運作情形,請前往 iframe 導覽功能示範

權限政策設定範例

如需下列設定的範例,請參閱示範

允許在所有來源使用這項功能

允許存取這項功能的所有來源架構

Permissions-Policy: geolocation=*
<iframe src="https://trusted-site.example" allow="geolocation">
<iframe src="https://ad.example" allow="geolocation">

如果來源清單設為 * 符記,系統就會允許在網頁上顯示的所有來源 (包括本身和所有 iframe) 使用這項功能。在這個範例中,從 https://your-site.example 提供的所有程式碼,以及從 https://trusted-site.example iframe 和 https://ad.example 提供的程式碼,皆可存取使用者瀏覽器中的地理位置功能。請記住,您必須在 iframe 上設定 allow 屬性,並且將來源新增至標頭來源清單。

您可以在示範中查看這項設定。

功能僅適用於來源相同

僅允許同源存取這項功能的架構

Permissions-Policy: geolocation=(self)

使用 self 權杖可讓地理位置資訊僅用於相同來源。跨來源將無法存取這項功能。在這個範例中,只有 https://trusted-site.example (self) 可以存取地理位置。如果您只想讓這項功能適用於自己的網頁,請使用這個語法。

您可以在示範影片中看到這項設定。

允許存取相同來源和特定跨來源的功能

可存取功能的指定來源架構

Permissions-Policy: geolocation=(self "https://trusted-site.example")

這個語法允許本身 (https://your-site.example) 和 https://trusted-site.example 使用地理位置。請務必在 iframe 標記中明確加入 allow 屬性。如果有另一個 iframe 包含 <iframe src="https://ad.example" allow="geolocation">https://ad.example 就無法存取地理位置功能。只有原始網頁和列於來源清單中的 https://trusted-site.example,以及在 iframe 標記中具有 allow 屬性的網頁,才能存取使用者功能。

您可以在示範影片中看到這項設定。

在所有來源中皆封鎖功能

所有遭封鎖的來源架構,無法存取這項功能

Permissions-Policy: geolocation=()

如果來源清單空白,則所有來源都會無法使用這項功能。您可以在示範影片中看到這項設定。

使用 JavaScript API

現有的 Feature Policy JavaScript API 會在文件或元素 (document.featurePolicy or element.featurePolicy) 中以物件形式出現。Permissions Policy 的 JavaScript API 尚未實作。

功能政策 API 可用於「權限」政策設定的政策,但有部分限制。我們仍有其他問題需要解決,才能導入 JavaScript API,因此已提出建議,將邏輯移至 Permissions API。如有任何想法,歡迎加入討論。

featurePolicy.allowsFeature(feature)

  • 如果此功能可用於預設來源用途,則傳回 true
  • Permissions Policy 和先前的 Feature Policy 設定的政策行為相同
  • 在 iframe 元素 (iframeEl.featurePolicy.allowsFeature('geolocation')) 上呼叫 allowsFeature() 時,傳回的值會反映 iframe 中是否設定了 allow 屬性

featurePolicy.allowsFeature(feature, origin)

  • 如果指定來源允許此功能,則傳回 true
  • 如果在 document 上呼叫方法,這個方法就不會再像功能政策那樣,告知您是否允許指定來源使用這項功能。現在,這個方法會指示該來源可能允許該功能。您必須額外檢查 iframe 是否已設定 allow 屬性。開發人員必須對 iframe 元素上的 allow 屬性進行額外檢查,以判定第三方來源是否可以使用這項功能。

使用 element 物件檢查 iframe 中的功能

您可以使用 element.allowsFeature(feature),因為它會考量 allow 屬性,而 document.allowsFeature(feature, origin) 則不會。

const someIframeEl = document.getElementById('some-iframe')
const isCameraFeatureAllowed = someIframeEl.featurePolicy.allowsFeature('camera')

featurePolicy.allowedFeatures()

  • 傳回允許使用預設來源的功能清單。
  • 權限政策和功能政策設定的兩項政策,行為皆相同
  • 如果相關聯的節點是 iframe,系統會考量 allow 屬性。

featurePolicy.features()

  • 傳回瀏覽器可用的功能清單。
  • 權限政策和功能政策設定的兩項政策,行為皆相同

Chrome 開發人員工具整合

Chrome 開發人員工具與權限政策整合

請查看權限政策在 DevTools 中的運作方式。

  1. 開啟 Chrome 開發人員工具
  2. 開啟「應用程式」面板,查看每個影格允許和不允許的功能。
  3. 在側欄中選取要檢查的框架。系統會列出所選影格可使用的功能,以及在該影格中遭到封鎖的功能。

從功能政策遷移

如果您使用 Feature-Policy 標頭,可以按照下列步驟遷移至權限政策。

將功能政策標頭替換為權限政策標頭

由於功能政策標頭僅適用於以 Chromium 為基礎的瀏覽器,且自 Chrome 88 版開始支援權限政策標頭,因此你可以放心透過權限政策更新現有的標頭。

Feature-Policy:
  autoplay *;
  geolocation 'self';
  camera 'self' 'https://trusted-site.example';
  fullscreen 'none';

使用功能政策之前。

新增
Permissions-Policy:
  autoplay=*,
  geolocation=(self),
  camera=(self "https://trusted-site.example"),
  fullscreen=()

新增權限政策。

更新 document.allowsFeature(feature, origin) 用量

如果您使用 document.allowsFeature(feature, origin) 方法檢查 iframe 允許的功能,請使用 iframe 元素附加的 allowsFeature(feature) 方法,不要使用所含 documentelement.allowsFeature(feature) 方法負責允許屬性,document.allowsFeature(feature, origin) 則不需要。

使用「document」檢查功能存取權

如要繼續使用 document 做為基本節點,您必須為 iframe 標記上的 allow 屬性進行額外檢查。

<iframe id="some-iframe" src="https://example.com" allow="camera"></iframe>
Permissions-Policy: camera=(self "https://example.com")
const isCameraPolicySet = document.featurePolicy.allowsFeature('camera', 'https://example.com')

const someIframeEl = document.getElementById('some-iframe')
const hasCameraAttributeValue = someIframeEl.hasAttribute('allow')
&& someIframeEl.getAttribute('allow').includes('camera')

const isCameraFeatureAllowed = isCameraPolicySet && hasCameraAttributeValue

建議您不要使用 document 更新現有程式碼,而是在 element 物件上呼叫 allowsFeature(),如前述範例所示。

Reporting API

Reporting API 可為網頁應用程式提供一致的回報機制,而針對權限政策違規的 Reporting API 則是實驗功能。

如要測試實驗功能,請按照逐步操作說明操作,並在 chrome://flags/#enable-experimental-web-platform-features 中啟用標記。啟用標記後,您可以在「應用程式」分頁的「DevTools」中查看權限政策違規情形:

以下範例說明如何建構報表 API 標頭:

Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"

Content-Security-Policy: script-src 'self'; object-src 'none'; report-to main-endpoint;
Document-Policy: document-write=?0; report-to=main-endpoint;

在目前的實作中,您可以像前一個例子一樣設定「default」端點,這樣一來,當該影格發生任何違規事件時,您就會收到這類違規報告。子頁框需要專屬的報表設定。

瞭解詳情

如要進一步瞭解權限政策,請參閱下列資源: