GitHub WebHook 使用教程

程序猿阿朗發表於2024-03-27

本文收錄於 Github.com/niumoo/JavaNotes,Java 系列文件,資料結構與演算法!
本文收錄於網站:https://www.wdbyte.com/,我的公眾號:程式猿阿朗

什麼是 WebHook

WebHook 直譯是網路鉤子,可以把 WebHook 看做一種通知方式,只要發生關注的事件,就會傳送通知到我們指定的 Web 服務。使用 WebHook 可以讓我們在關注的事件發生時收到通知,而不是不斷輪訓 API 確認事件是否發生,

GitHub 允許我們配置 WebHook ,它允許我們配置某個倉庫發生某個事件時,通知指定的外部服務。比如當指定倉庫有提交程式碼時,GitHub 將向我們配置的 API 傳送 POST 請求。以此可以實現相應的自動化操作,如持續整合 CI,請求程式碼稽核,拉取新程式碼編譯打包部署等。

發揮想象力,GitHub 的 WebHook 結合 GitHub Action 可以做很多事情,文末有具體例子。

這篇文章介紹 GitHub Web Hooks 的使用。

WebHook 配置

訪問

訪問 GitHub 倉庫的 Webhooks 設定頁面,開啟倉庫的 Settings 配置頁面,點選 Webhook Tab 頁。

也可以直接訪問連結:https://github.com/使用者/倉庫/settings/hooks

配置

點選 Add webhook 按鈕。

配置完成後,點選 Add webhook ,GitHub 會傳送一個 POST 請求到配置的 web 服務用於驗證是否正常。Web Hook 的事件會在請求頭 X-GitHub-Event 中進行標識。

如上面說到的 ping ,會在請求頭中進行標識:X-GitHub-Event: ping。’

一些說明:

  • Payload URL:此處填寫你的 Web 服務地址,最好已經存在,這樣 ping 事件才能正常響應。
  • Secret:安全金鑰,用於對請求體進行雜湊計算,用於驗證是否為 GitHub 傳送。後面部分會詳細介紹紹。
  • SSL Verification:是否啟用 SSL 驗證,如果你的 Web 服務啟用了 HTTPS,這裡應該選擇啟用,也建議啟用。
  • Just the push event:只訂閱倉庫 push 事件。

Ping 測試

點選 Add webhook 後傳送一個請求到配置的 Web 服務,下面是一個真實的 ping 事件請求頭資訊。

Request URL: https://www.wdbyte.com/api/github/webhook
Request method: POST
Accept: */*
Content-Type: application/x-www-form-urlencoded
User-Agent: GitHub-Hookshot/eb2eabb
X-GitHub-Delivery: 10957020-e918-11ee-8a3e-e0754488dbc
X-GitHub-Event: ping
X-GitHub-Hook-ID: 468323437
X-GitHub-Hook-Installation-Target-ID: 33701056
X-GitHub-Hook-Installation-Target-Type: repository
X-Hub-Signature: sha1=1877dfa1d840bdd5583af33718cea722d825ed7
X-Hub-Signature-256: sha256=addaf81ed2f5795f06ba096b1c863b00188d3444367b5125d2036e17ca324e3

WebHook 訊息驗證

因為配置的 Web 服務 URL 是一個開放的 URL,任何人都可以訪問,為了防止有人惡意構造 WebHook 訊息請求,我們應該對收到的請求進行驗證,判斷是否為來自 GitHub Web Hook 的請求。

如何驗證呢?是怎麼樣的一個流程呢?這時就要用到上面配置的 Secret 安全金鑰了。

具體步驟如下:

  1. GitHub WebHook 使用 Secret 對 Post Body 內容進行雜湊(HMAC 十六進位制摘要)計算,得到一個雜湊值,如 xxyyzz
  2. 將雜湊值存入請求頭 X-Hub-Signature-256 中,值以 sha256= 開頭,如 sha256=xxyyzz
  3. Web 服務收到請求,使用相同的 Secret 對 Post Body 進行相同雜湊演算法計算。得到一個摘要。
  4. 取出 X-Hub-Signature-256 請求頭的值進行比較,如果相同則表示請求來自 GitHub Web Hook。

下面是官方給出的 JavaScript 語言的驗證實現:

let encoder = new TextEncoder();

async function verifySignature(secret, header, payload) {
    let parts = header.split("=");
    let sigHex = parts[1];

    let algorithm = { name: "HMAC", hash: { name: 'SHA-256' } };

    let keyBytes = encoder.encode(secret);
    let extractable = false;
    let key = await crypto.subtle.importKey(
        "raw",
        keyBytes,
        algorithm,
        extractable,
        [ "sign", "verify" ],
    );

    let sigBytes = hexToBytes(sigHex);
    let dataBytes = encoder.encode(payload);
    let equal = await crypto.subtle.verify(
        algorithm.name,
        key,
        sigBytes,
        dataBytes,
    );

    return equal;
}

function hexToBytes(hex) {
    let len = hex.length / 2;
    let bytes = new Uint8Array(len);

    let index = 0;
    for (let i = 0; i < hex.length; i += 2) {
        let c = hex.slice(i, i + 2);
        let b = parseInt(c, 16);
        bytes[index] = b;
        index += 1;
    }

    return bytes;
}

這種對內容進行摘要計算的驗證方式其實很常見,在之前介紹過的 JWT 的原理中也有提到,感興趣的可以檢視:JSON Web Token 入門教程

注意:Secret 十分重要,應該妥善儲存,防止洩漏。更不要儲存到公開倉庫之中。要天不知地不知,GitHub 知你知。

Java 驗證 WebHook

網上有很多使用 Java 語言驗證 GitHub WebHook 訊息的程式碼實現,這裡使用第三方依賴進行驗證,省去雜湊演算法的編寫。

引入依賴:

<dependency>
    <groupId>am.ik.webhook</groupId>
    <artifactId>webhook-verifier</artifactId>
    <version>0.1.2</version>
</dependency>

訊息驗證:

private void verify(HttpServletRequest request, String body) {
    HmacWebhookSigner webhookSigner = new HmacWebhookSigner("SHA256", secret);
    WebhookVerifier verifier = new WebhookVerifier(webhookSigner, WebhookSigner.Encoder.HEX);
    String signature = request.getHeader(WebhookHttpHeaders.X_HUB_SIGNATURE_256);
    verifier.verify(body, signature);
}

驗證透過沒有任何返回,如果驗證失敗,會丟擲 WebhookAuthenticationException 異常。

WebHook 最佳實踐

遵循 WebHook 最佳實踐可以提高其安全性和效能,下面是一些常用建議。

  1. 只訂閱關注的事件,減少事件推送次數。
  2. 使用 HTTPS 提高安全性,HTTPS 已經是 Web 服務的標配。
  3. 配置白名單或驗證策略,確保訊息傳送方可信,比如文中提到的秘鑰雜湊驗證。
  4. 快速響應請求,很多 WebHook 推送對響應耗時有要求,比如 GitHub 是 10 秒,因此如果你的處理邏輯過於耗時,可以考慮非同步處理,優先響應。

最後推薦一下必應桌布網站https://bing.wdbyte.com/ ,這是一個使用 GitHub Action 自動抓取桌布,然後透過 WebHook 自動構建部署的專案,近期會對其網站進行升級,增加收藏,不同尺寸桌布下載功能,可以蹲下我的公眾號

歡迎 Star:https://github.com/niumoo/bing-wallpaper

相關文章:如何使用 Github Actions 自動抓取每日必應桌布?

本文收錄於 Github.com/niumoo/JavaNotes,Java 系列文件,資料結構與演算法!
本文收錄於網站:https://www.wdbyte.com/,我的公眾號:程式猿阿朗

相關文章