使用 Reporting API 監控安全性違規事項、已淘汰的 API 呼叫等。
有些錯誤只會在正式版中發生。您不會在本機或開發期間看到這些問題,因為實際使用者、實際網路和實際裝置會改變遊戲。Reporting API 可協助找出部分錯誤,例如網站上的安全性違規事項,或已淘汰和即將淘汰的 API 呼叫,並將這些錯誤傳送至您指定的端點。
這項功能可讓您使用 HTTP 標頭宣告要監控的項目,並由瀏覽器操作。
設定 Reporting API 後,您就能在使用者遇到這類錯誤時收到通知,進而修正問題。
這篇文章將說明這項 API 的功能和使用方式。讓我們深入瞭解!
總覽
假設您的網站 (site.example) 具有 Content-Security-Policy 和 Document-Policy。不瞭解這些功能的用途嗎?沒關係,您還是可以瞭解這個範例。
您決定監控網站,以便瞭解何時違反這些政策,同時也想留意程式碼集可能使用的已淘汰或即將淘汰的 API。
如要這麼做,請設定 Reporting-Endpoints 標頭,並視需要在政策中使用 report-to 指令對應這些端點名稱。
Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"
# Content-Security-Policy violations and Document-Policy violations
# will be sent to main-endpoint
Content-Security-Policy: script-src 'self'; object-src 'none'; report-to main-endpoint;
Document-Policy: document-write=?0; report-to=main-endpoint;
# Deprecation reports don't need an explicit endpoint because
# these reports are always sent to the `default` endpoint
發生不可預見的情況,導致部分使用者違反這些政策。
違規示例
index.html
<script src="script.js"></script>
<!-- CSP VIOLATION: Try to load a script that's forbidden as per the Content-Security-Policy -->
<script src="https://example.com/script.js"></script>
script.js,由index.html載入
// DOCUMENT-POLICY VIOLATION: Attempt to use document.write despite the document policy
try {
document.write('<h1>hi</h1>');
} catch (e) {
console.log(e);
}
// DEPRECATION: Call a deprecated API
const webkitStorageInfo = window.webkitStorageInfo;
瀏覽器會產生 CSP 違規報告、Document-Policy 違規報告和淘汰報告,記錄這些問題。
瀏覽器會稍作延遲 (最多一分鐘),然後將報表傳送到為這類違規事項設定的端點。報表會由瀏覽器本身 (而非伺服器或網站) 頻外傳送。
端點會接收這些報表。
現在可以存取這些端點的報告,並監控發生的錯誤。您可以開始排解影響使用者的問題。
範例報表
{
"age": 2,
"body": {
"blockedURL": "https://site2.example/script.js",
"disposition": "enforce",
"documentURL": "https://site.example",
"effectiveDirective": "script-src-elem",
"originalPolicy": "script-src 'self'; object-src 'none'; report-to main-endpoint;",
"referrer": "https://site.example",
"sample": "",
"statusCode": 200
},
"type": "csp-violation",
"url": "https://site.example",
"user_agent": "Mozilla/5.0... Chrome/92.0.4504.0"
}
應用實例和報表類型
您可以設定 Reporting API,監控網站上發生的許多類型的有趣警告或問題:
| 報告類型 | 產生報表的狀況範例 |
|---|---|
| CSP 違規 (僅限第 3 級) | 您在其中一個網頁上設定了Content-Security-Policy (CSP),但該網頁嘗試載入 CSP 不允許的指令碼。 |
| 違反 COOP | 您已在網頁上設定 Cross-Origin-Opener-Policy,但跨源視窗嘗試直接與文件互動。 |
| COEP 違規 | 您在網頁上設定了 Cross-Origin-Embedder-Policy,但文件包含未選擇由跨來源文件載入的跨來源 iframe。 |
| 記錄違反政策 | 網頁的文件政策禁止使用 document.write,但指令碼嘗試呼叫 document.write。 |
| 違反權限政策 | 網頁的權限政策禁止使用麥克風,但有要求音訊輸入的指令碼。 |
| 淘汰警告 | 網頁使用已淘汰或即將淘汰的 API,並直接呼叫該 API,或使用頂層第三方指令碼呼叫該 API。 |
| 介入 | 網頁嘗試執行的動作,基於安全性、效能或使用者體驗考量,瀏覽器決定不予執行。Chrome 範例:網頁在網路速度緩慢時使用 document.write,或在使用者尚未互動的跨源框架中呼叫 navigator.vibrate。 |
| 意外事故 | 瀏覽器在網站開啟時當機。 |
報表
瀏覽器會將報表傳送至您設定的端點。傳送的要求如下所示:
POST
Content-Type: application/reports+json
這些要求的酬載是報表清單。
報表清單範例
[
{
"age": 420,
"body": {
"columnNumber": 12,
"disposition": "enforce",
"lineNumber": 11,
"message": "Document policy violation: document-write is not allowed in this document.",
"policyId": "document-write",
"sourceFile": "https://site.example/script.js"
},
"type": "document-policy-violation",
"url": "https://site.example/",
"user_agent": "Mozilla/5.0... Chrome/92.0.4504.0"
},
{
"age": 510,
"body": {
"blockedURL": "https://site.example/img.jpg",
"destination": "image",
"disposition": "enforce",
"type": "corp"
},
"type": "coep",
"url": "https://dummy.example/",
"user_agent": "Mozilla/5.0... Chrome/92.0.4504.0"
}
]
以下是各報表提供的資料:
| 欄位 | 說明 |
|---|---|
age |
報表時間戳記與目前時間之間的毫秒數。 |
body |
實際報表資料,序列化為 JSON 字串。報表 body 中包含的欄位取決於報表的 type。⚠️ 不同類型的報表有不同的主體。
|
type |
報表類型,例如 csp-violation 或 coep。 |
url |
產生報表的文件或 worker 位址。使用者名稱、密碼和片段等私密資料會從這個網址中移除。 |
user_agent |
產生報表的要求的 User-Agent 標頭。 |
憑證報表
如果回報端點與產生報表的網頁來源相同,則會在包含報表的要求中收到憑證 (Cookie)。
憑證可提供實用的報表背景資訊,例如特定使用者的帳戶是否持續觸發錯誤,或是在其他網頁上採取特定動作順序時,是否會觸發這個網頁的報表。
瀏覽器何時及如何傳送報表?
報表會透過網站頻外傳送:瀏覽器會控管報表傳送至已設定端點的時間。此外,您也無法控制瀏覽器傳送報表的時間,瀏覽器會自動擷取、排入佇列,並在適當時間傳送報表。
也就是說,使用 Reporting API 時,幾乎不會有效能問題。
報表會延遲傳送 (最多一分鐘),以提高分批傳送報表的機率。這樣做可節省頻寬,避免耗用使用者網路連線的流量,這對行動裝置尤其重要。如果瀏覽器正在處理優先順序較高的工作,或使用者當時使用的網路速度緩慢或壅塞,瀏覽器也可能延遲傳送。
第三方和第一方問題
如果網頁發生違規或淘汰情形,系統會產生報表,並傳送至您設定的端點。包括網頁上執行的第三方指令碼違規。
如果違規或淘汰情形發生在網頁嵌入的跨源 iframe,系統不會回報給端點 (至少預設不會)。iframe 可以自行設定報表,甚至向您網站 (也就是第一方) 的報表服務回報,但這取決於框架網站。另請注意,只有在違反網頁政策時,系統才會產生大多數報表,且網頁政策和 iframe 政策不同。
含有淘汰項目的範例
瀏覽器支援
下表匯總了瀏覽器對 Reporting API v1 (即 Reporting-Endpoints 標頭) 的支援。除了「網路錯誤記錄」報表類型外,瀏覽器對 Reporting API v0 (Report-To 標頭) 的支援情形相同。新版 Reporting API 不支援「網路錯誤記錄」報表類型。詳情請參閱遷移指南。
| 報告類型 | Chrome | Chrome iOS 版 | Safari | Firefox | 邊緣 |
|---|---|---|---|---|---|
| CSP 違規 (僅限第 3 級)* | ✔ 是 | ✔ 是 | ✔ 是 | ✘ 否 | ✔ 是 |
| 網路錯誤記錄 | ✘ 否 | ✘ 否 | ✘ 否 | ✘ 否 | ✘ 否 |
| 違反 COOP/COEP | ✔ 是 | ✘ 否 | ✔ 是 | ✘ 否 | ✔ 是 |
| 所有其他類型:違反政策、淘汰、介入、當機 | ✔ 是 | ✘ 否 | ✘ 否 | ✘ 否 | ✔ 是 |
這個表格僅摘要說明新 Reporting-Endpoints 標頭對 report-to 的支援。如要遷移至 Reporting-Endpoints,請參閱 CSP 報告遷移提示。
使用 Reporting API
決定報表傳送位置
方法有以下兩種:
- 將報表傳送至現有的報表收集器服務。
- 將報表傳送至您自行建構及操作的報表收集器。
選項 1:使用現有的報表收集器服務
以下是幾個報表收集器服務範例:
如果您知道其他解決方案,請開啟問題通知我們,我們會更新這篇文章!
除了價格之外,選取報表收集器時,請考量下列幾點:🧐
- 這個收集器是否支援所有報表類型?舉例來說,並非所有回報端點解決方案都支援 COOP/COEP 報表。
- 你是否願意與第三方報表收集者分享應用程式的網址?即使瀏覽器從這些網址中移除私密資訊,私密資訊仍可能透過這種方式外洩。如果這對您的應用程式來說風險太高,請自行運作回報端點。
選項 2:建構及操作自己的報表收集器
自行建構接收報表的伺服器並非易事。如要開始,您可以建立輕量樣板的分支版本。這個應用程式是以 Express 建構,可接收及顯示報表。
建立自己的報表收集器時,請注意下列事項:
- 檢查
POST要求是否含有Content-Type,以辨識瀏覽器傳送至端點的報告要求。application/reports+json - 如果端點與網站位於不同來源,請確保端點支援 CORS 預檢要求。
選項 3:結合選項 1 和 2
您可能希望由特定供應商處理某些類型的報表,但其他報表則由內部解決方案處理。
在這種情況下,請按照下列方式設定多個端點:
Reporting-Endpoints: endpoint-1="https://reports-collector.example", endpoint-2="https://my-custom-endpoint.example"
設定Reporting-Endpoints標題
設定 Reporting-Endpoints 回應標頭。值必須是一組或多組以半形逗號分隔的鍵/值組合:
Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"
如果您要從舊版 Reporting API 遷移至新版 Reporting API,建議同時設定 Reporting-Endpoints 和 Report-To。詳情請參閱遷移指南。特別是,如果您只使用 report-uri 指令回報 Content-Security-Policy 違規事項,請參閱 CSP 回報功能的遷移步驟。
Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"
Report-To: ...
鍵 (端點名稱)
每個鍵都可以是您選擇的名稱,例如 main-endpoint 或 endpoint-1。您可以決定為不同報表類型設定不同的具名端點,例如 my-coop-endpoint、my-csp-endpoint。這樣一來,您就能根據報表類型,將報表轉送至不同的端點。
如要接收介入、淘汰、當機報表或上述報表的組合,請設定名為 default 的端點。
如果 Reporting-Endpoints 標頭未定義 default 端點,系統會產生這類報表,但不會傳送。
值 (網址)
每個值都是您選擇的網址,報表會傳送到該網址。這裡要設定的網址取決於您在步驟 1 中的決定。
端點網址:
- 開頭須為正斜線 (
/)。不支援相對路徑。 - 可以是跨來源,但如果是這種情況,憑證不會與報表一起傳送。
範例
Reporting-Endpoints: my-coop-endpoint="https://reports.example/coop", my-csp-endpoint="https://reports.example/csp", default="https://reports.example/default"
然後在適當的政策中使用每個具名端點,或在所有政策中使用單一端點。
要在哪裡設定標題?
在本文介紹的新版 Reporting API 中,報表範圍則限定為文件。也就是說,對於特定來源,site.example/page1 和 site.example/page2 等不同文件可以將報表傳送至不同端點。
如要接收網站任何網頁上發生的違規或淘汰情形報表,請將標頭設為所有回應的中介軟體。
以下是 Express 的範例:
const REPORTING_ENDPOINT_BASE = 'https://report.example';
const REPORTING_ENDPOINT_MAIN = `${REPORTING_ENDPOINT_BASE}/main`;
const REPORTING_ENDPOINT_DEFAULT = `${REPORTING_ENDPOINT_BASE}/default`;
app.use(function (request, response, next) {
// Set up the Reporting API
response.set(
'Reporting-Endpoints',
`main-endpoint="${REPORTING_ENDPOINT_MAIN}", default="${REPORTING_ENDPOINT_DEFAULT}"`,
);
next();
});
編輯政策
設定 Reporting-Endpoints 標頭後,請在要接收違規報告的每個政策標頭中,新增 report-to 指令。report-to 的值應為您設定的具名端點之一。
您可以將多個端點用於多項政策,也可以在不同政策中使用不同端點。

report-to 不適用於淘汰、介入和當機報告。這些報表未繫結至任何政策。只要設定 default 端點,系統就會產生報表,並傳送至這個 default 端點。
範例
# Content-Security-Policy violations and Document-Policy violations
# will be sent to main-endpoint
Content-Security-Policy: script-src 'self'; object-src 'none'; report-to main-endpoint;
Document-Policy: document-write=?0;report-to=main-endpoint;
# Deprecation reports don't need an explicit endpoint because
# these reports are always sent to the default endpoint
偵錯報表設定
刻意產生報表
設定 Reporting API 時,您可能需要刻意違反政策,檢查報表是否能正常產生及傳送。
節省時間
報告可能會延遲傳送 (約一分鐘),這在偵錯時是很長的時間。😴 幸好,在 Chrome 中進行偵錯時,您可以使用 --short-reporting-delay 旗標,在報表生成後立即收到。
在終端機中執行下列指令,啟用這個旗標:
YOUR_PATH/TO/EXECUTABLE/Chrome --short-reporting-delay
使用開發人員工具
在 Chrome 中,使用開發人員工具查看已傳送或即將傳送的報告。
截至 2021 年 10 月,這項功能仍在實驗階段。如要使用這項功能,請按照下列步驟操作:
- 使用 Chrome 96 以上版本 (在瀏覽器中輸入
chrome://version即可查看版本) - 在 Chrome 網址列中輸入或貼上
chrome://flags/#enable-experimental-web-platform-features。 - 按一下「已啟用」。
- 重新啟動瀏覽器。
- 開啟 Chrome 開發人員工具。
- 在 Chrome 開發人員工具中開啟「設定」。在「實驗」下方,按一下「在『應用程式』面板中啟用 Reporting API 面板」。
- 重新載入開發人員工具。
- 重新載入頁面。在開啟開發人員工具的頁面中,產生的報表會列在 Chrome 開發人員工具的「Application」(應用程式)面板中,位於「Reporting API」(Reporting API) 下方。
報表狀態
「狀態」欄會顯示檢舉是否已成功送出。
| 狀態 | 說明 |
|---|---|
Success |
瀏覽器已傳送報表,端點則以成功代碼 (200 或其他成功回應代碼 2xx) 回覆。 |
Pending |
瀏覽器正在嘗試傳送報告。 |
Queued |
報表已產生,瀏覽器不會嘗試傳送。在下列兩種情況下,報表會顯示為 Queued:
|
MarkedForRemoval |
經過一段時間 (Queued) 後,瀏覽器已停止嘗試傳送報告,並即將從待傳送報告清單中移除該報告。 |
無論報表是否成功傳送,一段時間後都會移除。
疑難排解
報表是否未產生,或未如預期傳送至端點?以下提供幾個疑難排解訣竅。
無法產生報表
開發人員工具中顯示的報表已正確產生。如果清單中未顯示您預期的報表:
- 請查看政策中的
report-to。如果設定錯誤,系統就不會產生報表。請前往「編輯政策」修正問題。如要進一步排解這個問題,請檢查 Chrome 中的開發人員工具控制台:如果控制台針對您預期的違規事項彈出錯誤訊息,表示您的政策可能已正確設定。 - 請注意,這份清單只會顯示在開啟開發人員工具的文件中產生的報表。舉例來說,如果您的網站
site1.example嵌入了違反政策的 iframesite2.example,因而產生報表,則只有在您於獨立視窗中開啟 iframe,並為該視窗開啟開發人員工具時,這份報表才會顯示在開發人員工具中。
報表已產生,但未傳送或未收到
如果開發人員工具中顯示報表,但端點未收到報表,該怎麼辦?
- 請務必使用短延遲。如果看不到報表,可能是因為報表尚未傳送。
檢查
Reporting-Endpoints標頭設定。如果排程有問題,系統就不會傳送正確產生的報表。在這種情況下,報表的狀態在開發人員工具中會維持Queued(嘗試傳送時,狀態可能會跳到Pending,然後快速返回Queued)。可能導致這種情況的常見錯誤:已使用端點,但未設定。範例:
Document-Policy: document-write=?0;report-to=endpoint-1; Reporting-Endpoints: default="https://reports.example/default"
文件政策違規報告應傳送至 endpoint-1,但這個端點名稱未在 Reporting-Endpoints 中設定。
缺少
default端點。部分報表類型 (例如淘汰和介入報表) 只會傳送至名為default的端點。詳情請參閱「設定 Reporting-Endpoints 標頭」。檢查政策標頭語法是否有問題,例如缺少引號。查看詳細資料。
確認端點可以處理傳入的要求。
請確認端點支援 CORS 預檢要求。否則無法接收報告。
測試端點的行為。如要這麼做,請模擬瀏覽器,傳送類似瀏覽器傳送的端點要求,不必手動產生報表。執行下列指令:
curl --header "Content-Type: application/reports+json" \ --request POST \ --data '[{"age":420,"body":{"columnNumber":12,"disposition":"enforce","lineNumber":11,"message":"Document policy violation: document-write is not allowed in this document.","policyId":"document-write","sourceFile":"https://dummy.example/script.js"},"type":"document-policy-violation","url":"https://dummy.example/","user_agent":"xxx"},{"age":510,"body":{"blockedURL":"https://dummy.example/img.jpg","destination":"image","disposition":"enforce","type":"corp"},"type":"coep","url":"https://dummy.example/","user_agent":"xxx"}]' \ YOUR_ENDPOINT端點應以成功代碼 (
200或其他成功回應代碼2xx) 回應。如果沒有,表示端點設定有問題。
相關檢舉機制
僅限報表
-Report-Only政策標頭和 Reporting-Endpoints 會搭配運作。
在 Reporting-Endpoints 中設定,並在 Content-Security-Policy、Cross-Origin-Embedder-Policy 和 Cross-Origin-Opener-Policy 的 report-to 欄位中指定的端點,會在違反這些政策時收到報告。
在 Reporting-Endpoints 中設定的端點也可以在 Content-Security-Policy-Report-Only、Cross-Origin-Embedder-Policy-Report-Only 和 Cross-Origin-Opener-Policy-Report-Only 的 report-to 欄位中指定。如果有人違反這些政策,他們也會收到報告。
雖然這兩種情況都會傳送報表,但 -Report-Only 標頭不會強制執行政策:不會有任何內容遭到封鎖或中斷,但您會收到報表,瞭解哪些內容可能遭到封鎖或中斷。
ReportingObserver
ReportingObserver JavaScript API 可協助您觀察用戶端警告。
ReportingObserver 和 Reporting-Endpoints 標頭產生的報表看起來相同,但用途略有不同。
在下列情況下使用 ReportingObserver:
- 您只想監控淘汰或瀏覽器干預措施。
ReportingObserver會顯示用戶端警告,例如淘汰和瀏覽器介入,但與Reporting-Endpoints不同,它不會擷取任何其他類型的報告,例如 CSP 或 COOP/COEP 違規。 - 你必須即時處理這些違規事項。
ReportingObserver可讓您將回呼附加至違規事件。 - 您想在報表中附加額外資訊,以便使用自訂回呼進行偵錯。
另一個差異是,ReportingObserver 只能在用戶端設定:即使您無法控管伺服器端標頭,也無法設定 Reporting-Endpoints,仍可使用這項功能。
延伸閱讀
- Reporting API 遷移指南:從 v0 遷移至 v1
- ReportingObserver
- 規格:舊版 Reporting API (第 0 版)
- 規格:新版 Reporting API (v1)
非常感謝 Ian Clelland、Eiji Kitamura 和 Milica Mihajlija 對本文件的評論和建議。