練習 - 使用祕密保護 Webhook 承載
在本練習中,您將使用祕密來保護您的 Webhook 承載,並了解如何使用 Azure 函式來驗證承載是否確實來自 GitHub。
取得您的 Azure 函式的金鑰
在 Azure 入口網站中,回到您在課程模組的第一個練習中所建立的函式應用程式。
在左側的功能表窗格中,選取 [函式] 下的 [函式]。 [函數應用程式] 的 [函式] 窗格隨即出現。
選取您建立的 HttpTrigger1。 您函式的 [HtttpTrigger1] 窗格隨即顯示。
在左側功能表窗格中,於 [開發人員] 底下,選取 [程式碼 + 測試]。 會針對您的函式顯示 [編碼 + 測試] 窗格。
在您函式的 index.js JavaScript 檔案中,於檔案開頭處
module.exports
陳述式上方,新增對 crypto-js 程式碼程式庫的參考。const Crypto = require('crypto');
在頂端功能列上,選取 [儲存]。 [記錄] 窗格會顯示在該窗格的底部。
在左側功能表窗格中,於 [開發人員] 底下,選取 [函式金鑰]。 會針對您的函式顯示 [函式金鑰] 窗格。
在 [值] 資料行底下,選取 [顯示值] 連結。
選取 [複製到剪貼簿] 圖示,並儲存此金鑰以便在下一個步驟中使用。
在左側功能表窗格中,於 [開發人員] 底下,選取 [程式碼 + 測試]。 會針對您的函式顯示 [編碼 + 測試] 窗格。
在程式碼區塊中,在
context.log
陳述式之後,新增下列程式碼。 將 <default key> 取代為您剛複製到剪貼簿的預設金鑰:const hmac = Crypto.createHmac("sha1", "<default key>"); const signature = hmac.update(JSON.stringify(req.body)).digest('hex');
此程式碼會使用 GitHub 相同機制計算金鑰的雜湊。
新增另一個將
sha1=
加到金鑰的開頭的const
,使其符合要求標頭中x-hub-signature
的格式。 將下列程式碼新增至您的函式。const shaSignature = `sha1=${signature}`;
新增下列程式碼,以從要求標頭擷取 GitHub 簽章:
const gitHubSignature = req.headers['x-hub-signature'];
比較兩個字串。 如果相符合,就處理要求,如下所示:
if (!shaSignature.localeCompare(gitHubSignature)) { // Existing code if (req.body.pages[0].title) { ... } else { ... } }
如果字串不相符,就傳回 HTTP 401 (未經授權) 回應,其中包含告知傳送者簽章不相符的訊息。
if (!shaSignature.localeCompare(gitHubSignature)) { ... } else { context.res = { status: 401, body: "Signatures don't match" }; }
完整的 函式如下所示:
const Crypto = require('crypto'); module.exports = async function (context, req) { context.log('JavaScript HTTP trigger function processed a request.'); const hmac = Crypto.createHmac("sha1", "<default key>"); const signature = hmac.update(JSON.stringify(req.body)).digest('hex'); const shaSignature = `sha1=${signature}`; const gitHubSignature = req.headers['x-hub-signature']; if (!shaSignature.localeCompare(gitHubSignature)) { if (req.body.pages[0].title) { context.res = { body: "Page is " + req.body.pages[0].title + ", Action is " + req.body.pages[0].action + ", Event Type is " + req.headers['x-github-event'] }; } else { context.res = { status: 400, body: ("Invalid payload for Wiki event") } } } else { context.res = { status: 401, body: "Signatures don't match" }; } };
在頂端功能列上,選取 [儲存]。 會出現 [記錄] 窗格並顯示一個「已連接!」的陳述。
更新 Webhook 祕密
在 GitHub 入口網站中,切換到您的 GitHub 帳戶。
選取您的存放庫。
在頂端功能列中,選取 [Settings] (設定)。 [設定] 窗格隨即出現。
在側邊欄中,選取 [Webhooks]。 [Webhooks] 窗格隨即出現。
按一下 Webhook 旁邊的 [Edit] \(編輯\)。
在 [祕密] 文字方塊中,輸入您先前在本練習中所儲存之函式的預設金鑰。
向下捲動至頁面底部,然後選取 [更新 Webhook]。 [Webhooks/管理 Webhook] 窗格隨即出現。
測試 Webhook 和 Azure 函式
選取 [Recent Deliveries] \(最近的傳遞項目\) 索引標籤。
選取省略符號 (...) 按鈕,以選取最新 (最上面) 的傳遞項目。
按一下 [Redeliver] \(重新傳遞\)。 在 [重新傳遞承載?] 對話方塊中,選取 [是,重新傳遞此承載]。
此動作會模擬您再次編輯您的 Wiki 頁面。
選取省略符號 (...) 按鈕,以選取最新 (最上面) 的傳遞項目。
在 [標頭] 區段中,您會看到
x-hub-signature
。 您也會看到回應碼為 200,表示已成功處理要求。Request URL: https://testwh123456.azurewebsites.net/api/HttpTrigger1?code=aUjXIpqdJ0ZHPQuB0SzFegxGJu0nAXmsQBnmkCpJ6RYxleRaoxJ8cQ%3D%3D Request method: POST content-type: application/json Expect: User-Agent: GitHub-Hookshot/16496cb X-GitHub-Delivery: ce122460-6aae-11e9-99d4-de6a298a424a X-GitHub-Event: gollum X-Hub-Signature: sha1=<hash of default key>
測試無效簽章
在 GitHub 入口網站的 [Webhook] 頁面上,選取 [設定] 索引標籤。
在 [祕密] 測試方塊中,選取 [變更祕密]。
輸入隨機字串、向下捲動,然後選取 [Update webhook] \(更新 Webhook\)。
Webhook 所使用的金鑰不再符合 Azure 函式預期的金鑰。
選取 [Recent Deliveries] \(最近的傳遞項目\) 索引標籤。
選取省略符號 (...) 按鈕,以選取最新 (最上面) 的傳遞項目。
選取 [重新傳遞],然後在出現的 [重新傳遞承載] 對話方塊中,選取 [是,重新傳遞此承載]。
這次,您會看到回應碼為 401,表示要求未經授權。
選取省略符號按鈕 (...),以選取最新 (頂端) 的傳遞項目 (重新傳遞)。
選取 [回應] 索引標籤,然後在 [本文] 區段中,確認出現「簽章不相符」的訊息。