功能政策簡介

摘要

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

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

簡介

打造專屬網路是一路成長的冒險旅程。想要建構一流的網頁應用程式,不僅要達到效能,還採用所有最新的最佳做法,就相當困難。隨著時間過去,提供優異體驗可能更困難。隨著專案不斷演進,開發人員會漸漸入手、推出新功能,以及不斷擴增程式碼集。您曾經獲得出色的體驗 TM,可能會開始拖慢速度,使用者體驗也會開始受到影響!功能政策的用意是協助您順利完成設定。

使用功能政策時,您需要為瀏覽器選擇採用一組「政策」,以執行網站所使用的特定功能。這些政策會限制網站對於特定功能的存取權,或修改瀏覽器的預設行為。

以下列舉幾項功能政策的用途:

  • 變更行動裝置和第三方影片上的 autoplay 預設行為
  • 限制網站使用敏感 API,例如 cameramicrophone
  • 允許 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,瀏覽器會封鎖該 API。即使使用者先前已授予分享位置資訊的權限也是如此

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

而在其他情況下,您則能稍微放寬這項政策。我們可以允許自己的來源使用 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">)。請注意,限制較多的政策會勝出。舉例來說,下列 iframe 無法進入全螢幕,因為 allow="fullscreen 'none'" 的限制比 allowfullscreen 嚴格:

<!-- 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 下存取主要文件,或為 iframe 存取 frame.featurePolicy

範例

以下範例說明在 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",
        ...

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

常見問題

使用功能政策的時機

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

因此,請謹慎使用 document-writesync-xhr 等其他政策。因此開啟這些警告可能會導致廣告等第三方內容無法正常運作。另一方面,請使用功能政策檢查,確保您的網頁絕對不會使用這些難以執行的 API!

是否會在開發或正式環境使用功能政策?

兩者。我們建議在開發期間啟用政策,並在實際工作環境中啟用政策。在開發期間啟用政策可協助您從正確的方向著手。這可協助您在發生任何非預期迴歸時找出問題將實際工作環境中的政策保持在啟用狀態,保證為使用者提供特定使用者體驗。

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

Reporting API 現已正式推出!如同網站可選擇接收與 CSP 違規淘汰項目相關的報告,您也能接收外部的功能政策違規報告。

iframe 內容有哪些沿用規則?

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

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

不可以。政策的生命週期適用於單一網頁導覽回應,如果使用者前往新頁面,就必須在新回應中明確傳送 Feature-Policy 標頭,才能套用政策。

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

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

目前 Chrome 是唯一支援功能政策的瀏覽器。不過,由於整個 API 介面為選擇啟用或功能可偵測,因此功能政策本身可以充分採用漸進式強化

結論

功能政策有助於提供光線充足的途徑,改善使用者體驗和效能。這在開發或維護應用程式時特別有用,因為這可以避免在潛在的腳槍滲入程式碼集前出現。

其他資源