You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP中Twilio签名验证失败问题排查求助

解决Twilio Webhook签名验证失败(含Cloudflare环境适配)

核心问题分析

你的代码漏传了Twilio签名验证必需的POST请求参数,同时Cloudflare作为反向代理会修改请求头与URL,两者共同导致验证失败。

具体修复步骤

1. 补全验证方法的POST参数

Twilio的RequestValidator::validate()方法需要三个参数:签名、请求URL、POST表单参数。你的代码仅传入前两个,这是验证失败的核心原因。需补充获取POST参数并传入:

// 获取Twilio发送的POST参数
$postParams = $_POST;
// 验证时传入第三个参数
if ($validator->validate($signature, $url, $postParams)) {
    // 验证通过逻辑
}

2. 修正Cloudflare环境下的URL生成逻辑

Cloudflare作为反向代理时,服务器端$_SERVER变量会被修改,需用Cloudflare传递的真实请求头构建Twilio实际请求的URL:

  • 协议:从X-Forwarded-Proto头获取(Cloudflare可能以HTTPS访问你的服务器,但服务器内部使用HTTP)
  • 主机:从X-Forwarded-Host头获取,或确认HTTP_HOST为正确的外部域名
  • 请求路径:保留REQUEST_URI即可,若Cloudflare有特殊修改可尝试X-Original-URI

修改后的URL生成代码:

// 从Cloudflare头获取真实协议
$protocol = $_SERVER['HTTP_X_FORWARDED_PROTO'] ?? 'https';
// 获取真实主机
$host = $_SERVER['HTTP_X_FORWARDED_HOST'] ?? $_SERVER['HTTP_HOST'];
// 构建正确的URL
$url = $protocol . '://' . $host . $_SERVER['REQUEST_URI'];

3. 调整Cloudflare设置避免请求篡改

Cloudflare的部分功能会修改请求内容,导致签名验证失败,需针对Webhook路径设置例外:

  • 关闭该路径的Rocket Loader
  • 关闭该路径的Auto Minify(尤其是HTML/JS/CSS压缩,会影响请求体)
  • 在Cloudflare的Security > WAF中,为Webhook路径添加允许规则,避免请求被拦截

4. 调试验证逻辑

添加调试代码,对比Twilio发送的签名与本地计算的签名,精准定位问题:

// 计算本地预期的签名
$expectedSignature = $validator->computeSignature($url, $postParams);
error_log("Expected signature: " . $expectedSignature);
error_log("Received signature: " . $signature);

若两者不一致,说明URL或POST参数与Twilio发送的内容不匹配,需进一步排查。

修改后的完整代码

<?php
require '/path/to/vendor/autoload.php';
use Twilio\Security\RequestValidator;
use Twilio\TwiML\VoiceResponse;

// Load configuration from the ini file
$config = parse_ini_file('/path/to/config.ini', true);
if (!$config) {
    error_log("Failed to parse config.ini");
    $response = new VoiceResponse();
    $response->say("Failed to parse config.ini");
    header('Content-Type: text/xml');
    echo $response;
    exit;
}

$token = $config['twilio']['token'];
$validator = new RequestValidator($token);

$signature = $_SERVER['HTTP_X_TWILIO_SIGNATURE'] ?? '';
// 适配Cloudflare的URL生成
$protocol = $_SERVER['HTTP_X_FORWARDED_PROTO'] ?? 'https';
$host = $_SERVER['HTTP_X_FORWARDED_HOST'] ?? $_SERVER['HTTP_HOST'];
$url = $protocol . '://' . $host . $_SERVER['REQUEST_URI'];

// 获取POST参数
$postParams = $_POST;

$response = new VoiceResponse();

// 调试:输出预期签名
$expectedSignature = $validator->computeSignature($url, $postParams);
error_log("Expected signature: " . $expectedSignature);
error_log("Received signature: " . $signature);

if ($validator->validate($signature, $url, $postParams)) {
    $response->say("Confirmed to have come from Twilio.");
    error_log("Confirmed to have come from Twilio.");
} else {
    error_log("Invalid Twilio signature received");
    error_log("URL used for validation: " . $url);
    $server_data = print_r($_SERVER, true);
    error_log("Server Data: " . $server_data);
    error_log("POST Params: " . print_r($postParams, true));
    $response->reject();
}

header('Content-Type: text/xml');
echo $response;

?>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 21:37:43