在Node.js中验证Github webhooks请求

Published on
Published on
/3 mins read/---

Webhooks为应用程序提供了一种在Github发生新事件时接收实时信息的方式。 确保webhook请求来自Github并相应地处理它是很重要的。

这是如何在Remix应用(或任何Node.js服务器)中简单验证webhook签名的方法。

github.ts
import type { ActionFunction } from '@remix-run/node'
import { json } from '@remix-run/node'
import crypto from 'crypto'
 
// `loader` 函数处理路由的GET请求
// 在这种情况下,我们返回400状态,因为我们只想处理POST请求
// 了解更多关于Remix路由的loader:https://remix.run/docs/en/route/loader
export let loader = () => {
  return json({ message: 'Bad request!' }, { status: 400 })
}
 
// `action` 函数处理路由的非GET请求
// 了解更多关于Remix路由的action:https://remix.run/docs/en/route/action
export let action: ActionFunction = async ({ request }) => {
  // 如果请求方法不是POST,返回405状态
  if (request.method !== 'POST') {
    return json({ message: 'Method not allowed' }, 405)
  }
 
  // 验证webhook签名
  let signature = request.headers.get('X-Hub-Signature-256')
  let rawBody = await request.text()
  let webhookSecret = process.env.GITHUB_APP_WEBHOOK_SECRET
  let hmac = crypto.createHmac('sha256', webhookSecret)
  hmac.update(rawBody)
  let generatedSignature = `sha256=${hmac.digest('hex')}`
  if (signature !== generatedSignature) {
    return json({ message: 'Webhook must originate from GitHub!' }, 400)
  }
 
  let event = request.headers.get('X-GitHub-Event')
  console.log(`✅ Github webhook验证成功!事件:"${event}"`)
 
  try {
    let payload = JSON.parse(rawBody)
    if (event === 'your_subscribed_event') {
      let { action, sender, ...rest } = payload
      // 对来自Github的payload进行处理
      // `action` 是触发事件的动作
      // `sender` 是触发事件的用户
    }
    return json({ message: 'Webhook处理成功!', event }, 200)
  } catch (err) {
    console.log(`❌ 处理webhook事件时出错:${err?.toString()}`)
    // 向Github返回200状态以避免重试
    // 即使webhook payload在你的应用中没有成功处理
    return json({ message: 'Webhook已处理!', event }, 200)
  }
}

如果你觉得这个代码片段有用,可以在你的应用中随意使用!

Happy verifying!