功能政策簡介

摘要

功能政策可讓網頁開發人員選擇性地啟用、停用及修改瀏覽器中特定 API 和網頁功能的行為。CSP 類似,但前者會控管功能,而不是控管安全性!

功能政策本身是開發人員和瀏覽器之間的選擇加入式協議,有助於我們達成建構 (及維護) 優質網頁應用程式的目標。

簡介

為網路建構應用程式是一項艱鉅的任務,想要建構一流的網頁應用程式,不僅要達到效能,還採用所有最新的最佳做法,就相當困難。要持續提供優質體驗,更是難上加難。隨著專案演進,開發人員加入團隊,新功能陸續推出,程式碼庫也會隨之擴大。您曾經獲得優異的體驗 TM,可能會開始變得越來越惡劣,使用者體驗也會開始受到影響!這項政策旨在協助你依照計畫前進。

透過功能政策,您可以選擇採用一組「政策」,讓瀏覽器針對網站中使用的特定功能強制執行。這些政策會限制網站對於特定功能的存取權,或修改瀏覽器的預設行為。

以下列舉幾個可透過功能政策執行的操作:

  • 變更行動裝置和第三方影片上 autoplay預設行為
  • 限制網站使用 cameramicrophone 等敏感 API。
  • 允許 iframe 使用 fullscreen API。
  • 禁止使用同步 XHR 和 document.write() 等過時 API。
  • 請確認圖片的大小合適 (例如避免版面配置衝突),且不會過大而影響可視區域 (例如浪費使用者的頻寬)。

政策是開發人員與瀏覽器之間的契約。這類 ID 會向瀏覽器說明開發人員的意圖,因此當我們的應用程式嘗試停止操作,並做出不良行為時,可協助我們誠實告知。如果網站或嵌入的第三方內容試圖違反開發人員預先選取的任何規則,瀏覽器會以更優異的使用者體驗覆寫該行為,或完全封鎖 API。

使用功能政策

功能政策提供兩種控制功能的方式:

  1. 透過 Feature-Policy HTTP 標頭。
  2. 在 iframe 上使用 allow 屬性。

如要使用功能政策,最簡單的方法是傳送含有網頁回應的 Feature-Policy HTTP 標頭。這個標頭的值是您希望瀏覽器針對特定來源遵循的政策或政策組合:

Feature-Policy: <feature> <allow list origin(s)>

來源允許清單可能有多種不同的值:

  • *:這項功能可在頂層瀏覽情境和巢狀瀏覽情境 (iframe) 中使用。
  • 'self':頂層瀏覽情境和相同來源的巢狀瀏覽情境允許使用這項功能。在巢狀瀏覽情境中的跨來源文件中,此方法是禁止的。
  • 'none':這項功能在頂層瀏覽情境和巢狀瀏覽情境中皆不允許使用。
  • <origin(s)>:要啟用政策的特定來源 (例如 https://example.com)。

範例

假設您要禁止整個網站使用 Geolocation API您可以為 geolocation 功能傳送 'none' 的嚴格許可清單,即可達到這項目的:

Feature-Policy: geolocation 'none'

如果程式碼或 iframe 嘗試使用 Geolocation API,瀏覽器會封鎖該程式碼或 iframe。即使使用者先前已授予分享位置資訊的權限,也是如此

違反設定的地理位置政策
違反設定的地理位置政策。

而在其他情況下,您則能稍微放寬這項政策。我們可以允許自己的來源使用 Geolocation API,但在許可清單中設定 'self',防止第三方內容存取該 API:

Feature-Policy: geolocation 'self'

iframe allow 屬性

使用功能政策的第二種方式,是用於控管 iframe 中的內容。使用 allow 屬性指定內嵌內容的政策清單:

<!-- Allow all browsing contexts within this iframe to use fullscreen. -->
<iframe src="https://example.com..." allow="fullscreen"></iframe>

<!-- Equivalent to: -->
<iframe src="https://example.com..." allow="fullscreen *"></iframe>

<!-- Allow only iframe content on a particular origin to access the user's location. -->
<iframe
  src="https://another-example.com/demos/..."
  allow="geolocation https://another-example.com"
></iframe>

現有的 iframe 屬性會怎麼樣?

部分由功能政策控管的功能已具有可控管其行為的屬性。舉例來說,<iframe allowfullscreen> 是可讓 iframe 內容使用 HTMLElement.requestFullscreen() API 的屬性。此外,還有 allowpaymentrequestallowusermedia 屬性,分別允許 Payment Request APIgetUserMedia()

盡量使用 allow 屬性,而非這些舊屬性。如果您需要使用 allow 屬性搭配相等的舊版屬性來支援回溯相容性,則完全沒有問題 (例如 <iframe allowfullscreen allow="fullscreen">)。請注意,限制較多的政策會勝出。舉例來說,由於 allow="fullscreen 'none'"allowfullscreen 更嚴格,因此下列 iframe 無法進入全螢幕模式:

<!-- Blocks fullscreen access if the browser supports feature policy. -->
<iframe allowfullscreen allow="fullscreen 'none'" src="..."></iframe>

一次控制多項政策

您可以傳送 HTTP 標頭,並附上以 ; 分隔的政策指令清單,藉此同時控制多項功能:

Feature-Policy: unsized-media 'none'; geolocation 'self' https://example.com; camera *;

也可以為每項政策傳送個別標頭:

Feature-Policy: unsized-media 'none'
Feature-Policy: geolocation 'self' https://example.com
Feature-Policy: camera *;

此範例會進行下列操作:

  • 禁止在所有瀏覽情境中使用 unsized-media
  • 禁止在所有瀏覽情境中使用 geolocation,但網頁本身的來源和 https://example.com 除外。
  • 允許 camera 存取所有瀏覽內容。

範例:在 iframe 上設定多項政策

<!-- Blocks the iframe from using the camera and microphone
     (if the browser supports feature policy). -->
<iframe allow="camera 'none'; microphone 'none'"></iframe>

JavaScript API

雖然 Chrome 60 已支援在 iframe 上使用 Feature-Policy HTTP 標頭和 allow 屬性,但 Chrome 74 新增了 JavaScript API

這個 API 可讓用戶端程式碼判斷網頁、頁框或瀏覽器允許哪些功能。您可以透過 document.featurePolicy (主文件) 或 frame.featurePolicy (iframe) 存取其內容。

範例

以下範例說明在網站 https://example.com 上傳送 Feature-Policy: geolocation 'self' 政策的結果:

/* @return {Array<string>} List of feature policies allowed by the page. */
document.featurePolicy.allowedFeatures();
// → ["geolocation", "midi",  "camera", "usb", "autoplay",...]

/* @return {boolean} True if the page allows the 'geolocation' feature. */
document.featurePolicy.allowsFeature('geolocation');
// → true

/* @return {boolean} True if the provided origin allows the 'geolocation' feature. */
document.featurePolicy.allowsFeature(
  'geolocation',
  'https://another-example.com/'
);
// → false

/* @return {Array<string>} List of feature policies allowed by the browser
regardless of whether they are in force. */
document.featurePolicy.features();
// → ["geolocation", "midi",  "camera", "usb", "autoplay",...]

/* @return {Array<string>} List of origins (used throughout the page) that are
   allowed to use the 'geolocation' feature. */
document.featurePolicy.getAllowlistForFeature('geolocation');
// → ["https://example.com"]

政策清單

那麼可透過功能政策控管哪些功能?

目前缺乏有關實作政策和使用方式的說明文件。隨著不同瀏覽器採用規格並實施各種政策,這份清單也會隨之增加。功能政策會不斷調整,因此需要提供良好的參考文件。

目前有幾種方法可查看可控制的功能。

  • 請參閱功能政策綜合示範。其中包含已在 Blink 中實作的各項政策範例。
  • 如要查看功能名稱清單,請參閱 Chrome 的來源
  • 請在 about:blank 上查詢 document.featurePolicy.allowedFeatures(),找出清單:
        ["geolocation",
         "midi",
         "camera",
         "usb",
         "magnetometer",
         "fullscreen",
         "animations",
         "payment",
         "picture-in-picture",
         "accelerometer",
         "vr",
        ...
  • 請前往 chromestatus.com,查看已在 Blink 中實作或正在考慮的政策。

如要確認上述部分政策的使用方式,請參閱規格的 GitHub 存放區其中包含一些政策的說明。

常見問題

何時該使用功能政策?

所有政策都必須選擇加入,因此請在適當的情況下使用功能政策。舉例來說,如果您的應用程式是圖片庫,maximum-downscaling-image 政策可協助您避免將大量圖片傳送至行動裝置可視區域。

document-writesync-xhr 等其他政策則應謹慎使用。開啟這些功能可能會導致廣告等第三方內容無法正常運作。另一方面,功能政策可做為檢查依據,確保網頁絕不會使用這些糟糕的 API!

我要在開發階段還是正式環境中使用功能政策?

兩者皆是。建議您在開發期間啟用政策,並在正式版中保持政策處於啟用狀態。在開發期間啟用政策可協助您從正確的方向著手。這有助於您在任何意外的回歸發生前先行偵測。在正式版中保持政策啟用狀態,確保使用者能享有特定的使用者體驗。

可以向我的伺服器檢舉違反政策的情形嗎?

Reporting API 正在開發中!就像網站可以選擇接收有關CSP 違規淘汰的報告一樣,您也可以接收有關功能政策違規的報告。

iframe 內容的繼承規則為何?

指令碼 (第一方或第三方) 會繼承其瀏覽內容的政策。也就是說,頂層指令碼會沿用主要文件的政策。

iframe 會沿用其上層頁面的政策。如果 iframe 具有 allow 屬性,則以父頁面和 allow 清單之間的較嚴格政策為準。如要進一步瞭解 iframe 的用法,請參閱 allow 屬性在 iframe 上的用法

否。政策的生命週期是針對單一網頁導覽回應。如果使用者前往新頁面,則必須在新的回應中明確傳送 Feature-Policy 標頭,政策才能套用。

哪些瀏覽器支援「功能政策」?

如需瀏覽器支援的最新資訊,請造訪 caniuse.com

目前 Chrome 是唯一支援功能政策的瀏覽器。不過,由於整個 API 途徑都是選擇加入或可偵測功能,功能政策非常適合漸進式增強功能。

結論

功能政策可協助您提供明確的路徑,以便提升使用者體驗和成效。在開發或維護應用程式時,這項功能特別實用,因為它可在潛在的陷阱進入程式碼集之前,協助您避免這些陷阱。

其他資源