Skip to main content
We publish frequent updates to our documentation, and translation of this page may still be in progress. For the most current information, please visit the English documentation.

保护 Webhook

出于安全原因,请确保您的服务器仅接收预期的 GitHub 请求。

一旦服务器配置为接收有效负载,它将侦听发送到您配置的端点的任何有效负载。 出于安全原因,您可能需要将请求限制为来自 GitHub 的请求。 有几种方法可以做到这一点(例如,可以选择允许来自 GitHub 的 IP 地址的请求),但更简单的方法是设置一个密钥令牌并验证信息。

可以使用 REST API 来管理存储库、组织和应用 Webhook。 可以列出 Webhook 的 Webhook 交付,获取并重新交付 Webhook 的个别交付,该交付可以集成到外部应用或服务中。 还可使用 REST API 更改 Webhook 的配置。 例如,您可以修改有效负载 URL、内容类型、SSL 验证和机密。 有关详细信息,请参阅:

设置密钥令牌

您需要在两个地方设置您的密钥令牌:GitHub 和您的服务器。

要在 GitHub 上设置令牌:

  1. 导航到要在其中设置 Webhook 的存储库。
  2. 填写密钥文本框。 使用高熵值随机字符串(例如,通过在终端获取 ruby -rsecurerandom -e 'puts SecureRandom.hex(20)' 的输出)。 Webhook 机密令牌字段
  3. 单击“更新 Webhook”****。

接下来,在服务器上设置存储此令牌的环境变量。 通常,这简单如运行以下命令:

$ export SECRET_TOKEN=YOUR-TOKEN

切勿将令牌硬编码到应用中!

验证来自 GitHub 的有效负载

设置密钥令牌后,GitHub Enterprise Server 使用它为每个有效负载创建一个哈希签名。 此哈希签名作为 x-hub-signature-256 包含在每个请求的标头中。

注意:为了向后兼容,我们还会包含使用 SHA-1 哈希函数生成的 x-hub-signature 标头。 如果可能,建议使用 x-hub-signature-256 标头来提高安全性。 下面的示例演示了如何使用 x-hub-signature-256 标头。

例如,如果您有一个侦听 web 挂钩的基本服务器,则配置可能类似于:

require 'sinatra'
require 'json'

post '/payload' do
  request.body.rewind
  push = JSON.parse(request.body.read)
  "I got some JSON: #{push.inspect}"
end

目的是使用你的 SECRET_TOKEN 计算哈希值,并确保结果与来自 GitHub Enterprise Server 的哈希匹配。 GitHub Enterprise Server 使用 HMAC 十六进制摘要计算哈希,因此您可以重新配置服务器,如下所示:

post '/payload' do
  request.body.rewind
  payload_body = request.body.read
  verify_signature(payload_body)
  push = JSON.parse(payload_body)
  "I got some JSON: #{push.inspect}"
end

def verify_signature(payload_body)
  signature = 'sha256=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), ENV['SECRET_TOKEN'], payload_body)
  return halt 500, "Signatures didn't match!" unless Rack::Utils.secure_compare(signature, request.env['HTTP_X_HUB_SIGNATURE_256'])
end

注意:Webhook 有效负载可以包含 unicode 字符。 如果您的语言和服务器实现指定了字符编码,请确保您将有效负载处理为 UTF-8。

您的语言和服务器实现可能与此示例代码不同。 但是,需要指出一些非常重要的事情:

  • 无论使用哪种实现方式,哈希签名都使用机密令牌和有效负载主体的密钥,以 sha256= 开头。

  • 不建议使用普通的 == 运算符。 像 secure_compare 这样的方法会执行“恒定时间”字符串比较,这有助于缓解针对常规相等运算符的某些定时攻击。