You need to enable JavaScript to run this app. 如何配置Nginx处理带Secret的Github Webhook POST请求
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Nginx处理带Secret的Github Webhook POST请求

Nginx 接收并验证GitHub Webhook 实现方案

现有前提与需求

  • GitHub Webhook 已完成基础配置:Payload URL 为https://myUrl/payload,预设校验密钥为thisisthesecret
  • 已有全局nginx.conf基础配置如下:
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}
  • 核心需求:
    • 仅响应指向/payload的POST类型GitHub Webhook请求
    • 校验请求签名与预设密钥thisisthesecret匹配
    • 校验通过后返回固定响应OK
    • 自动存储请求payload到本地持久化路径

此前网络上仅找到零散参考示例,无完整可落地的实现方案。

前置依赖说明

纯Nginx原生配置无法完成HMAC-SHA256签名校验逻辑,需要使用带ngx_http_lua_module的Nginx发行版,推荐直接使用OpenResty,无需额外编译模块,开箱即用。

可落地配置实现

所有自定义站点配置放在全局nginx.conf指向的/etc/nginx/conf.d/目录下,新建webhook.conf文件,内容如下:

# 提前创建payload存储目录并给nginx运行用户权限:mkdir -p /var/www/webhook_payload && chown -R nginx:nginx /var/www/webhook_payload
server {
    listen 80;
    server_name myUrl; # 替换为你的实际域名

    # 允许最大1M的payload,适配GitHub Webhook常规请求大小
    client_max_body_size 1m;
    client_body_buffer_size 1m;

    # 仅匹配/payload的POST请求
    location = /payload {
        # 禁用请求体缓冲,直接读取完整内容用于校验和存储
        lua_need_request_body on;

        default_type text/plain;

        # Lua逻辑实现签名校验、payload存储
        access_by_lua_block {
            local secret = "thisisthesecret"
            local signature_header = ngx.var.http_x_hub_signature_256

            -- 缺失签名头直接拒绝
            if not signature_header then
                ngx.exit(ngx.HTTP_FORBIDDEN)
            end

            -- 分离签名头的算法和实际值
            local algo, recv_sig = signature_header:match("(%w+)=(.+)")
            if not algo or algo ~= "sha256" then
                ngx.exit(ngx.HTTP_FORBIDDEN)
            end

            -- 计算请求体的HMAC-SHA256值
            local resty_hmac = require "resty.hmac"
            local hmac = resty_hmac:new(secret, resty_hmac.ALGOS.SHA256)
            local calc_sig = hmac:final(ngx.req.get_body_data(), true)

            -- 签名不匹配直接拒绝
            if calc_sig ~= recv_sig then
                ngx.exit(ngx.HTTP_FORBIDDEN)
            end

            -- 校验通过:存储payload到指定目录,文件名用时间戳+客户端IP避免重名
            local file_name = ngx.var.time_iso8601:gsub("[:/]", "-") .. "_" .. ngx.var.remote_addr .. ".json"
            local file_path = "/var/www/webhook_payload/" .. file_name
            local f, err = io.open(file_path, "w")
            if not f then
                ngx.log(ngx.ERR, "存储payload失败: ", err)
                ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
            end
            f:write(ngx.req.get_body_data())
            f:close()

            -- 返回固定响应OK
            ngx.say("OK")
        }
    }
}

生效步骤

  • 先执行nginx -t校验配置语法是否正确
  • 执行nginx -s reload重载配置生效
  • 可通过GitHub Webhook的测试发送功能验证校验逻辑、payload存储是否正常

内容的提问来源于stack exchange,提问作者jrz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.02 19:15:08