文档

0002-00000040

更新时间:

问题描述

使用OSS的API接口或SDK时,提示“SignatureDoesNotMatch”签名报错。

<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>SignatureDoesNotMatch</Code>
  <Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
  <RequestId>646DCB189AE2D1333018****</RequestId>
  <HostId>bucket.oss-cn-hangzhou.aliyuncs.com</HostId>
  <OSSAccessKeyId>LTAI******** </OSSAccessKeyId>
  <SignatureProvided>tPN3LTAI******** </SignatureProvided>
  <StringToSign>PUT\n\n\nTue, 23 May 2023 15:24:55 GMT\n/bucket/?acl</StringToSign>
  <StringToSignBytes>50 55 54 0A 0A 0A 54 75 65 2C 20 32 33 20 4D 61 79 20 32 30 32 33 20 31 35 3A 32 34 3A 35 35 20 47 4D 54 0A 2F 64 69 6E 61 72 79 2F 3F 61 63 6C </StringToSignBytes>
  <EC>0002-00000040</EC>
</Error>

问题原因

使用API接口或者SDK访问OSS时,客户端需要携带签名信息以供OSS服务端进行身份认证。如果服务器返回如上所示的响应,说明您在请求中提供的签名与服务端计算的不一致,导致请求被拒绝。

问题示例

  • 通过微信小程序请求OSS返回签名失败,通过浏览器请求OSS返回签名正常。

  • 请求到达OSS之前经过了客户端代理,且客户端代理对签名后的请求进行了修改,例如增加了新的请求头。

  • 使用CDN域名发起Head请求时,CDN把Head请求默认转为了Get请求。

    HEAD /ObjectName?objectMeta HTTP/1.1
    Host: your.cdn.com
    Date: Fri, 24 Feb 2012 06:38:30 GMT
    Authorization: OSS qn6q**************:77Dv****************
  • 通过CDN配置x-oss-range-behavior: standard请求头用于修改OSS Range回源,OSS在计算签名时将所有带x-oss-前缀的请求头加入计算。

  • Endpoint使用了CNAME域名,但初始化时没有打开CNAME开关。

    <?php
    if (is_file(__DIR__ . '/../autoload.php')) {
        require_once __DIR__ . '/../autoload.php';
    }
    if (is_file(__DIR__ . '/../vendor/autoload.php')) {
        require_once __DIR__ . '/../vendor/autoload.php';
    }
    
    use OSS\OssClient;
    use OSS\Core\OssException;
    $accessKeyId = getenv("OSS_ACCESS_KEY_ID");
    $accessKeySecret = getenv("OSS_ACCESS_KEY_SECRET");
    $endpoint = "https://your.cname.com";
    
    try {
        // Endpoint使用了CNAME域名,但初始化时没有打开CNAME开关。
        $isCNAME = false;
        $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, $isCNAME);
    } catch (OssException $e) {
        print $e->getMessage();
    }
  • 计算的签名中包含了加号(+),没有进行URL编码。

    GET /oss.jpg?OSSAccessKeyId=nz2p**********&Expires=1141889120&Signature=ab+cd HTTP/1.1
    Host: oss-example.oss-cn-hangzhou.aliyuncs.com
    Date: Fri, 24 Feb 2012 06:38:30 GMT

解决方案

请求出现签名报错时,请参考以下步骤进行排查。

  1. 确认签名所用的AccessKey ID与AccessKey Secret是否填写正确。

    您可以使用AccessKey ID与AccessKey Secret登录ossbrowser来验证正确性。具体步骤,请参见安装并登录ossbrowser

  2. 检查签名算法是否正确。

    OSS提供两种携带签名的请求方式,分别为在Header中包含签名在URL中包含签名。关于这两种签名方式的算法说明如下:

    • 在Header中包含签名

      StringToSign = VERB + "\n"
                    + Content-MD5 + "\n" 
                    + Content-Type + "\n" 
                    + Date + "\n" 
                    + CanonicalizedOSSHeaders
                    + CanonicalizedResource
      Signature = base64(hmac-sha1(AccessKeySecret, StringToSign)
    • 在URL中包含签名

      StringToSign = VERB + "\n" 
                    + CONTENT-MD5 + "\n" 
                    + CONTENT-TYPE + "\n" 
                    + EXPIRES + "\n" 
                    + CanonicalizedOSSHeaders
                    + CanonicalizedResource
      Signature = urlencode(base64(hmac-sha1(AccessKeySecret, StringToSign)))

    如果业务场景允许,推荐您使用SDK访问OSS,免去手动计算签名的过程。具体步骤,请参见使用阿里云SDK发起请求概述

  3. 比对响应体中的StringToSign字段与您发起请求的内容是否存在差异。

    StringToSign字段表示待签字符串,即签名算法中需要使用AccessKey Secret进行加密的内容。

    请求示例如下:

    PUT /bucket/abc?acl
    Date: Wed, 24 May 2023 02:12:30 GMT
    Authorization: OSS qn6q**************:77Dv****************
    x-oss-abc: mymeta

    以上请求计算得到的待签字符串应为:

    PUT\n\n\nWed, 24 May 2023 02:12:30 GMT\nx-oss-abc:mymeta\n/bucket/abc?acl
  4. 排查签名错误原因后,根据不同签名错误场景,选择对应的解决方法。

    签名错误场景示例

    解决方法

    微信小程序请求OSS返回签名失败,通过浏览器请求OSS返回签名正常。

    参考步骤3比对响应体中的StringToSign字段,查看微信小程序发起的请求是否携带了额外的Content-Type字段。如果请求中携带了Content-type,则signature计算也要加上Content-type。

    客户端代理修改了签名后的请求。

    参考步骤3比对响应体中的StringToSign字段与您发起请求的内容是否存在差异。

    通过CDN域名发起Head请求,CDN默认将Head请求自动转为Get请求。

    • 使用OSS默认域名发起Head请求。

    • 配置自定义回源头。

      默认情况下,您发起的Head请求经过阿里云CDN节点之后再访问源站时,会被自动转换为Get请求方式。如果您希望保持Head请求回源的方式,您可以按以下要求配置自定义回源头。具体操作,请参见配置回源HTTP请求头(旧版)

        • 自定义参数:Ali-Swift-Fwd-Head。

        • 取值:on

        重要

        该操作会针对全域名生效,需要慎重选择。

    CDN添加了新的请求头x-oss-range-behavior: standard

    您需要在客户端发起请求时,将x-oss-range-behavior: standard请求头加入签名计算。

    使用自定义域名请求OSS时,未打开CNAME开关。

    通过Java SDK打开CNAME开关的方式为setSupportCname(true)。

    关于其他语言SDK打开CNAME开关的说明,请参见SDK简介

    URL签名中签名计算结果包含加号(+)。

    对签名进行URL编码后再发起请求。

    GET /oss.jpg?OSSAccessKeyId=nz2p**********&Expires=1141889120&Signature=ab%2Bcd HTTP/1.1
    Host: oss-example.oss-cn-hangzhou.aliyuncs.com
    Date: Fri, 24 Feb 2012 06:38:30 GMT