几许温柔 發表於 2024-3-27 09:09:00

GitHub WebHook 使用教程

<p><img src="https://img2024.cnblogs.com/blog/1202902/202403/1202902-20240327090722316-1898424085.png"></p>
<blockquote>
<p>本文收录于 Github.com/niumoo/JavaNotes,Java 系列文档,数据结构与算法!<br>
本文收录于网站:https://www.wdbyte.com/,我的公众号:程序猿阿朗</p>
</blockquote>
<h2 id="什么是-webhook">什么是 WebHook</h2>
<p>WebHook 直译是网络钩子,可以把 WebHook 看做一种通知方式,只要发生关注的事件,就会发送通知到我们指定的 Web 服务。使用 WebHook 可以让我们在关注的事件发生时收到通知,而不是不断轮训 API 确认事件是否发生,</p>
<p>GitHub 允许我们配置 WebHook ,它允许我们配置某个仓库发生某个事件时,通知指定的外部服务。比如当指定仓库有提交代码时,GitHub 将向我们配置的 API 发送 POST 请求。以此可以实现相应的自动化操作,如持续集成 CI,请求代码审核,拉取新代码编译打包部署等。</p>
<blockquote>
<p>发挥想象力,GitHub 的 WebHook 结合 GitHub Action 可以做很多事情,文末有具体例子。</p>
</blockquote>
<p>这篇文章介绍 GitHub Web Hooks 的使用。</p>
<h2 id="webhook-配置">WebHook 配置</h2>
<h3 id="访问">访问</h3>
<p>访问 GitHub 仓库的 Webhooks 设置页面,打开仓库的 <code>Settings</code> 配置页面,点击 <code>Webhook</code> Tab 页。</p>
<p>也可以直接访问链接:<code>https://github.com/用户/仓库/settings/hooks</code></p>
<h3 id="配置">配置</h3>
<p>点击 <code>Add webhook</code> 按钮。</p>
<p><img src="https://img2024.cnblogs.com/blog/1202902/202403/1202902-20240327090805668-281974796.png"></p>
<p>配置完成后,点击 <code>Add webhook</code> ,GitHub 会发送一个 POST 请求到配置的 web 服务用于验证是否正常。Web Hook 的事件会在请求头 <code>X-GitHub-Event</code> 中进行标识。</p>
<p>如上面说到的 <code>ping</code> ,会在请求头中进行标识:<code>X-GitHub-Event: ping</code>。’</p>
<p>一些说明:</p>
<ul>
<li><strong>Payload URL</strong>:此处填写你的 Web 服务地址,最好已经存在,这样 <code>ping</code> 事件才能正常响应。</li>
<li><strong>Secret</strong>:安全密钥,用于对请求体进行哈希计算,用于验证是否为 GitHub 发送。后面部分会详细介绍绍。</li>
<li><strong>SSL Verification</strong>:是否启用 SSL 验证,如果你的 Web 服务启用了 HTTPS,这里应该选择启用,也建议启用。</li>
<li><strong>Just the push event</strong>:只订阅仓库 push 事件。</li>
</ul>
<h3 id="ping-测试">Ping 测试</h3>
<p>点击 <code>Add webhook</code> 后发送一个请求到配置的 Web 服务,下面是一个真实的 <code>ping</code> 事件请求头信息。</p>
<pre><code class="language-shell">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
</code></pre>
<h2 id="webhook-消息验证">WebHook 消息验证</h2>
<p>因为配置的 Web 服务 URL 是一个开放的 URL,任何人都可以访问,为了防止有人恶意构造 WebHook 消息请求,我们应该<strong>对收到的请求进行验证</strong>,判断是否为来自 GitHub Web Hook 的请求。</p>
<p>如何验证呢?是怎么样的一个流程呢?这时就要用到上面配置的 <code>Secret</code> 安全密钥了。</p>
<p>具体步骤如下:</p>
<ol>
<li>GitHub WebHook <strong>使用 Secret 对 Post Body 内容进行哈希</strong>(HMAC 十六进制摘要)计算,得到一个哈希值,如 <code>xxyyzz</code>。</li>
<li>将哈希值存入请求头 <code>X-Hub-Signature-256</code> 中,值以 <code>sha256=</code> 开头,如 <code>sha256=xxyyzz</code>。</li>
<li>Web 服务收到请求,使用相同的 Secret 对 Post Body 进行相同哈希算法计算。得到一个摘要。</li>
<li>取出 <code>X-Hub-Signature-256</code> 请求头的值进行比较,如果相同则表示请求来自 GitHubWeb Hook。</li>
</ol>
<p>下面是官方给出的 JavaScript 语言的验证实现:</p>
<pre><code class="language-javascript">let encoder = new TextEncoder();

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

    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 &lt; hex.length; i += 2) {
      let c = hex.slice(i, i + 2);
      let b = parseInt(c, 16);
      bytes = b;
      index += 1;
    }

    return bytes;
}
</code></pre>
<p>这种对内容进行摘要计算的验证方式其实很常见,在之前介绍过的 JWT 的原理中也有提到,感兴趣的可以查看:JSON Web Token 入门教程</p>
<blockquote>
<p>注意:Secret 十分重要,应该妥善保存,防止泄漏。更不要存储到公开仓库之中。要天不知地不知,GitHub 知你知。</p>
</blockquote>
<h2 id="java-验证-webhook">Java 验证 WebHook</h2>
<p>网上有很多使用 Java 语言验证 GitHub WebHook 消息的代码实现,这里使用第三方依赖进行验证,省去哈希算法的编写。</p>
<p>引入依赖:</p>
<pre><code class="language-xml">&lt;dependency&gt;
    &lt;groupId&gt;am.ik.webhook&lt;/groupId&gt;
    &lt;artifactId&gt;webhook-verifier&lt;/artifactId&gt;
    &lt;version&gt;0.1.2&lt;/version&gt;
&lt;/dependency&gt;
</code></pre>
<p>消息验证:</p>
<pre><code class="language-java">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);
}
</code></pre>
<p>验证通过没有任何返回,如果验证失败,会抛出 <code>WebhookAuthenticationException</code> 异常。</p>
<h2 id="webhook-最佳实践">WebHook 最佳实践</h2>
<p>遵循 WebHook 最佳实践可以提高其安全性和性能,下面是一些常用建议。</p>
<ol>
<li>只订阅关注的事件,减少事件推送次数。</li>
<li>使用 HTTPS 提高安全性,HTTPS 已经是 Web 服务的标配。</li>
<li>配置白名单或验证策略,确保消息发送方可信,比如文中提到的秘钥哈希验证。</li>
<li>快速响应请求,很多 WebHook 推送对响应耗时有要求,比如 GitHub 是 10 秒,因此如果你的处理逻辑过于耗时,可以考虑异步处理,优先响应。</li>
</ol>
<hr>
<p>最后推荐一下必应壁纸网站https://bing.wdbyte.com/ ,这是一个使用 GitHub Action 自动抓取壁纸,然后通过 WebHook 自动构建部署的项目,近期会对其网站进行升级,增加收藏,不同尺寸壁纸下载功能,可以蹲下我的公众号。</p>
<p>欢迎 Star:https://github.com/niumoo/bing-wallpaper</p>
<p>相关文章:如何使用 Github Actions 自动抓取每日必应壁纸?</p>
<blockquote>
<p>本文收录于 Github.com/niumoo/JavaNotes,Java 系列文档,数据结构与算法!<br>
本文收录于网站:https://www.wdbyte.com/,我的公众号:程序猿阿朗</p>
</blockquote><br><br>
来源:https://www.cnblogs.com/niumoo/p/18098155
頁: [1]
查看完整版本: GitHub WebHook 使用教程