保护 web 挂钩

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

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

The webhook REST APIs enable you to manage repository, organization, and app webhooks. You can also use the REST API to change the configuration of the webhook. 例如,您可以修改有效负载 URL、内容类型、SSL 验证和机密。 更多信息请参阅:

设置密钥令牌

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

要在 GitHub 上设置令牌:

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

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

$ export SECRET_TOKEN=your_token

切勿将令牌硬编码到您的应用程序中!

验证来自 GitHub 的有效负载

设置密钥令牌后,GitHub Enterprise Server 使用它为每个有效负载创建一个哈希签名。 This hash signature is included with the headers of each request as 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

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

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

  • No matter which implementation you use, the hash signature starts with sha256=, using the key of your secret token and your payload body.

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

此文档对您有帮助吗?

隐私政策

帮助我们创建出色的文档!

所有 GitHub 文档都是开源的。看到错误或不清楚的内容了吗?提交拉取请求。

做出贡献

或者, 了解如何参与。