我的个人博客

验证GitHub Webhook请求

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

当你设置GitHub webhook时,你可以提供一个密钥,GitHub将使用该密钥对每个请求进行签名。 这样,你就可以验证请求是否真的来自GitHub,而不是来自恶意攻击者。

设置webhook

在GitHub仓库中,导航到设置 > Webhooks > 添加webhook

GitHub Webhook设置

密钥字段中,输入一个随机字符串。这将是你的密钥,用于验证请求。

验证请求

当GitHub向你的webhook端点发送请求时,它会在X-Hub-Signature-256头中包含一个签名。 这个签名是使用你的密钥对请求体进行HMAC SHA-256哈希计算得出的。

要验证请求,你需要使用相同的密钥对请求体进行哈希计算,然后将结果与GitHub提供的签名进行比较。

以下是使用Node.js验证请求的示例:

verify-github-webhook.js
import crypto from 'crypto'
 
export function verifyGithubWebhook(req, secret) {
  const signature = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(req.body))
    .digest('hex')
  const trusted = Buffer.from(`sha256=${signature}`, 'ascii')
  const untrusted = Buffer.from(
    req.headers['x-hub-signature-256'] || '',
    'ascii'
  )
  return crypto.timingSafeEqual(trusted, untrusted)
}

然后,你可以在你的webhook处理程序中使用这个函数:

webhook-handler.js
import { verifyGithubWebhook } from './verify-github-webhook'
 
export default async function handler(req, res) {
  const { method } = req
 
  if (method !== 'POST') {
    res.setHeader('Allow', ['POST'])
    return res.status(405).json({
      error: { message: `Method ${method} Not Allowed` },
    })
  }
 
  // 验证请求
  const isValid = verifyGithubWebhook(req, process.env.GITHUB_WEBHOOK_SECRET)
  if (!isValid) {
    return res.status(401).json({ error: { message: 'Unauthorized' } })
  }
 
  // 处理webhook
  const { body } = req
  const { action, repository } = body
 
  // 做一些事情...
 
  return res.status(200).json({ success: true })
}

记得将你的GitHub webhook密钥添加到环境变量中:

.ENV.env
GITHUB_WEBHOOK_SECRET=你的github_webhook_密钥

就是这样!现在你可以安全地验证来自GitHub的webhook请求了。