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

使用Guzzle 3调用AWS Secrets Manager API报错400及签名异常求助

问题排查修复点

  • 时间戳一致性问题:你代码中多处调用new DateTime('UTC')生成时间,不同位置生成的时间可能存在秒级甚至分钟级差异,AWS签名要求所有参与签名计算、请求头传递的时间必须完全一致。请在代码最开始生成一次全局UTC时间,所有位置复用该值即可。
  • Host头格式错误:构造规范请求的canonical_headers时,Host头不需要带https://前缀,也不能有尾部空格,正确格式为host:secretsmanager.{你的区域ID}.amazonaws.com。
  • 规范请求构造错误:
    1. 规范请求中的URI路径/GetSecretValue不能带前后多余空格
    2. 规范请求必须包含请求Body的SHA256哈希值,你当前构造时遗漏了该字段
    3. 你在Authorization头的SignedHeaders中声明了content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target,但构造canonical_headers时未加入x-amz-content-sha256、x-amz-target两个头,签名参与的头和声明的头不匹配直接导致签名校验失败。
  • Guzzle 3 请求参数格式错误:Guzzle 3的post方法第二个参数是配置数组,请求头必须放在headers子数组下,你直接将头键值放在第二层,Guzzle不会将其识别为请求头,导致实际发出的请求和签名用的参数不一致。
  • 硬编码值错误:Authorization头中的Credential你硬编码了ACCESSKEYID和固定日期20210526,需要替换成代码中实际的$access_key和动态生成的$amzdate2。

核心修复代码示例

try {
    // 只生成一次时间,全局复用
    $utcNow = new DateTime('UTC');
    $amzdate = $utcNow->format('Ymd\THis\Z');
    $amzdate2 = $utcNow->format('Ymd');
    $secretKey = "你的AWS密钥";
    $access_key = "你的AWS访问键";
    $region = REGIONID;
    $service = 'secretsmanager';
    $alg = 'sha256';
    $algorithm = 'AWS4-HMAC-SHA256';
    // 补全所有参与签名的头
    $signed_headers = 'content-type;host;x-amz-date;x-amz-target';
    $payload = json_encode(array('SecretId' => '你的SecretID'));
    $payloadHash = hash('sha256', $payload);

    // 修正host头,补全所有需要签名的头
    $canonical_headers = "content-type:application/x-amz-json-1.1\n"
        . "host:secretsmanager.".$region.".amazonaws.com\n"
        . "x-amz-date:".$amzdate."\n"
        . "x-amz-target:secretsmanager.GetSecretValue\n";

    // 修正规范请求,去掉路径空格,补全payload哈希
    $canonical_request = "POST\n"
        . "/GetSecretValue\n"
        . "\n"
        . $canonical_headers . "\n"
        . $signed_headers . "\n"
        . $payloadHash;

    $credential_scope = $amzdate2 . '/' . $region . '/' . $service . '/' . 'aws4_request';
    $string_to_sign  = "AWS4-HMAC-SHA256\n"
        . $amzdate . "\n"
        . $credential_scope . "\n"
        . hash('sha256', $canonical_request);
    
    // 签名计算部分保持不变
    $kSecret = 'AWS4' . $secretKey;
    $kDate = hash_hmac($alg, $amzdate2, $kSecret, true);
    $kRegion = hash_hmac($alg, $region, $kDate, true);
    $kService = hash_hmac($alg, $service, $kRegion, true);
    $kSigning = hash_hmac($alg, 'aws4_request', $kService, true);
    $signature = hash_hmac('sha256', $string_to_sign, $kSigning);

    $client = new Client();
    $url = 'https://secretsmanager.' . $region . '.amazonaws.com/GetSecretValue';
    // 修正Guzzle3头的传参格式
    $request = $client->post(
        $url,
        array(
            'headers' => array(
                'Content-Type' => 'application/x-amz-json-1.1',
                'X-Amz-Target' => 'secretsmanager.GetSecretValue',
                'X-Amz-Date' => $amzdate,
                'Authorization' => sprintf(
                    'AWS4-HMAC-SHA256 Credential=%s/%s, SignedHeaders=%s, Signature=%s',
                    $access_key,
                    $credential_scope,
                    $signed_headers,
                    $signature
                )
            )
        ),
        $payload
    );

    $response = json_decode($client->send($request)->getBody(true));
    var_dump($response);
} catch(Guzzle\Http\Exception\ClientErrorResponseException $e){
    echo '<pre>',var_dump($e->getResponse()->getBody()),'</pre>';
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 21:57:03