題干與適用場景
擴充功能只在使用者主動點擊工具列按鈕後處理目前頁面,接著把篩選後的欄位送到受控後端。不需要背景掃描所有分頁,也不需要讀取任意網站的 Cookie。請提出 Manifest V3 權限拆分、執行期流程、失敗降級與上線驗證方案。
題目考察瀏覽器擴充功能的權限邊界與產品化安全。服務端仍須做身分驗證、資料最小化與稽核;擴充功能權限不能取代這些控制。
面試官考察點
面試官會看你是否把「能呼叫哪些 API」、「能存取哪些主機」與「使用者何時同意」分開。Chrome 文件分別處理 API 權限、主機權限、可選權限與 activeTab;權限會影響可用 API、URL、安裝警告及升級行為。
高品質回答從最小能力開始,解釋為何一次性的目前頁面操作不應預設申請 <all_urls>,並涵蓋拒絕、撤銷、升級與遙測。只說「加上 permissions」而不談權限生命週期,無法證明安全邊界。
回答前需要澄清的問題
- 「目前頁面」是否包含特殊頁面、跨來源 iframe、檔案 URL 或無痕視窗?
- API 是否必須讀取完整正文,還是只需使用者選取的欄位?
- 是否需要在使用者未點擊時持續監聽頁面變化?
- 支援 Chrome、Firefox 還是多個 WebExtensions 實作?
- 企業版是否會透過政策預先設定權限,稽核欄位保留多久?
30 秒回答框架
「我先把能力拆成目前頁面讀取、後端通訊與儲存。目前頁面的一次性操作優先使用 activeTab,不申請全站主機權限;只有確實需要跨頁持續工作時,才把精確主機模式放入 optionalhostpermissions,在使用者觸發功能時申請。API 權限只宣告必要項目,拒絕或撤銷就停止處理並提供手動複製降級。升級前比較權限差異,監控新增權限與資料流,回復時撤銷新能力。」
分步驟深入解答
第一步:把功能對應到權限
storage、scripting 等 API 權限解決擴充功能 API 能力;主機權限決定可互動的 URL 範圍。權限清單不應按「以後可能用到」添加,而應按每條資料流寫出最小範圍。
只處理使用者點擊所在分頁時,可以從以下方案開始:
{
"manifest_version": 3,
"permissions": ["activeTab", "scripting", "storage"],
"optional_host_permissions": ["https://app.example.com/*"]
}若只在目前頁面注入腳本,activeTab 會在使用者操作後提供暫時存取,分頁關閉或導覽後失效。若產品需要背景持續處理 app.example.com,再評估精確的可選主機權限,不把 :///* 當成預設方案。
第二步:設計漸進授權流程
安裝時只請求核心、低風險能力。使用者點擊「分析此頁」後,先確認目前 URL 是否在允許範圍;首次需要額外主機時呼叫 chrome.permissions.request(),在介面解釋用途、範圍與退出方式。
const granted = await chrome.permissions.request({
origins: ["https://app.example.com/*"]
});
if (!granted) {
showManualCopyFallback();
return;
}申請成功只代表瀏覽器能力可用,不能跳過服務端驗證。申請失敗、使用者稍後撤銷或政策停用時,程式應回到無權限狀態,不反覆彈窗打擾使用者。
第三步:區分 active、granted 與可撤銷狀態
Chromium 文件區分目前生效權限與歷史授予權限。chrome.permissions.remove() 會降低目前能力,但歷史授予集合可能仍記錄該權限;再次申請時未必再次顯示提示。因此產品應以「目前可用」作為執行判斷,並在設定頁提供明確撤銷入口。
每次任務開始前呼叫 chrome.permissions.contains() 檢查實際權限;任務中監聽 permissions.onRemoved,立即停止讀取與上傳、清除待送佇列,並記錄可稽核的權限變更事件。
第四步:處理拒絕、升級與回復
權限被拒絕時顯示不依賴技術術語的下一步:改用手動選取、複製貼上或離開。不要把拒絕當成網路錯誤,也不要在背景自動重試申請。
版本升級前產生權限差異清單:新增 API、主機模式、內容腳本匹配範圍與資料欄位分別審批。Chrome 在權限提升時可能停用擴充功能並等待使用者重新同意;刪除權限也不代表歷史授予集合被清空,所以回復測試要涵蓋「舊版本曾獲准」與「從未獲准」兩類使用者。
第五步:把權限做成可驗證的安全邊界
內容腳本暴露在網頁輸入影響下,訊息處理要做來源、訊息類型與資料長度驗證;服務端對擴充功能身分、使用者身分、目標資源與欄位白名單再次授權。主機權限只限制瀏覽器能力,不保證網頁本身可信,也不阻止擴充功能把已讀資料送到錯誤的後端。
上線前建立矩陣:首次安裝、允許與拒絕、撤銷、導覽後 activeTab 失效、可選主機申請、升級增加權限、回復、企業政策停用、瀏覽器不支援與離線。遙測只記錄權限鍵、主機模式、結果與版本,不記錄頁面正文。
高品質示範回答
「我會先畫出能力與資料流。工具列點擊後只處理目前頁面,所以核心方案使用 activeTab、scripting 與必要的 storage,不申請全站存取。只有背景持續處理 app.example.com 才把精確主機模式放到可選權限,並在使用者觸發功能時申請。申請前說明用途與範圍,拒絕後提供手動選取,不循環彈窗。
每次任務前檢查目前權限,監聽撤銷事件;權限失效就停止讀取、清理待送佇列,並讓服務端重新驗證身分與資源。升級前比較 API、主機與內容腳本差異,驗證新增權限導致的停用、重新同意與回復路徑。最後用權限矩陣與匿名化遙測驗證:沒有背景掃描、沒有跨主機注入、沒有頁面正文進入日誌,且拒絕與撤銷都能安全降級。」
常見錯誤
- 預設申請
<all_urls>→ 擴大讀取與注入面並增加使用者警告 → 先用activeTab,持續場景再精確申請主機。 - 把
optionalhostpermissions當成自動授權 → 宣告不等於使用者同意 → 在功能觸發時申請並處理拒絕。 - 只檢查安裝時權限 → 使用者之後可以撤銷,目前能力會變化 → 任務前檢查並監聽移除事件。
- 升級只看程式碼差異 → 新權限可能導致擴充功能被停用 → 比較權限集合並測試舊授予狀態。
- 把瀏覽器權限當成服務端授權 → 擴充功能仍可能把資料送錯帳戶 → 服務端重做身分、資源與欄位驗證。
- 權限申請塞滿技術名詞 → 使用者難以形成正確風險判斷 → 用用途、範圍與退出方式解釋。
追問及應對
追問一:為什麼不直接申請 <all_urls>?
目前頁面的一次性操作不需要背景存取所有網站。activeTab 在使用者操作後提供暫時能力,降低長期暴露面;只有明確的持續跨頁需求才值得評估精確主機範圍。
追問二:使用者撤銷權限後,已上傳的資料怎麼辦?
撤銷只能阻止後續瀏覽器存取,不能追回已離開裝置的資料。服務端應按最小欄位、短留存與可刪除策略設計;擴充功能立即清理本地待送佇列,並向使用者說明已完成的處理範圍。
追問三:可選權限申請後為何仍要做後端驗證?
瀏覽器權限只回答擴充功能能否讀取某個頁面,不回答使用者是否有權存取業務資源。後端必須驗證工作階段、擴充功能版本、目標資源與欄位白名單,拒絕過期或異常請求。
追問四:Chrome 與 Firefox 的權限行為能直接假設一致嗎?
不能。兩者共享 WebExtensions 概念,但提示文案、匹配模式與執行期邊界可能不同。應針對目標瀏覽器實測安裝、申請、撤銷、導覽與升級,並把差異寫入相容性矩陣。