当你设置GitHub webhook时,你可以提供一个密钥,GitHub将使用该密钥对每个请求进行签名。 这样,你就可以验证请求是否真的来自GitHub,而不是来自恶意攻击者。
设置webhook
在GitHub仓库中,导航到设置 > Webhooks > 添加webhook。
在密钥字段中,输入一个随机字符串。这将是你的密钥,用于验证请求。
验证请求
当GitHub向你的webhook端点发送请求时,它会在X-Hub-Signature-256
头中包含一个签名。 这个签名是使用你的密钥对请求体进行HMAC SHA-256哈希计算得出的。
要验证请求,你需要使用相同的密钥对请求体进行哈希计算,然后将结果与GitHub提供的签名进行比较。
以下是使用Node.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处理程序中使用这个函数:
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密钥添加到环境变量中:
GITHUB_WEBHOOK_SECRET=你的github_webhook_密钥
就是这样!现在你可以安全地验证来自GitHub的webhook请求了。