相关参考Reference

    常见签名认证错误排查

    签名认证中常见以下问题,你可以配合签名排查工具在线排查签名问题,或者通过如下的排查说明进行一一排查:

    不能正确区分URL中的URI部分和QueryString部分

    假设请求的URL是/v1/settings/region/list?type=public,此处URI应该为/v1/settings/region/list,type=public是querystring。但是客户端并没有正确区分它们,在计算签名时把/v1/settings/region/list?type=public都当成了PATH,进而得到的CanonicalRequest,因此传送的签名也有问题。 而服务端在验证签名使用的

    	# 客户端请求的CanonicalRequest:
    	GET
    	/v1/settings/region/list%3ftype%3dpublic
    	host:settings.bce-internal.baidu.com
    	x-bce-date:2017-02-15T08%3A52%3A48Z

    服务端向IAM构造验签请求时,传递的是正确的URI和QueryString部分:

    	{
    	  "auth" : {
    	    "authorization" : "bce-auth-v1/f3e1f5c2ef9c4d25b7f8b936861cd175/2017-04-05T08:29:50Z/3600/host;x-bce-date/9a48ec83ffb6c486892c4985df7dc6bc20f7c7bebb483f8f355592b8503a3f59",
    	    "request" : {
    	      "method" : "GET",
    	      "uri" : "/v1/settings/region/list",
    	      "headers" : {
    	        "host" : "settings.bce-internal.baidu.com",
    	        "x-bce-date": "2017-02-15T08:52:48Z"
    	      },
    	      "params": {
    	        "type": "public"
    	      }
    	    }
    	  }

    进而,IAM基于服务提供的请求信息,演算签名时URI与客户端不一致,得到的签名必然与请求值不一致。

    URI尾部的"/"不一致

    客户端请求:

    	# 客户端请求的CanonicalRequest:
    	GET
    	/v1/settings/region/list
    	host:settings.bce-internal.baidu.com
    	x-bce-date:2017-02-15T08%3A52%3A48Z

    服务端向IAM构造验签请求时,误将URI多写了个尾部的"/":

    	{
    	  "auth" : {
    	    "authorization" : "bce-auth-v1/f3e1f5c2ef9c4d25b7f8b936861cd175/2017-04-05T08:29:50Z/3600/host;x-bce-date/9a48ec83ffb6c486892c4985df7dc6bc20f7c7bebb483f8f355592b8503a3f59",
    	    "request" : {
    	      "method" : "GET",
    	      "uri" : "/v1/settings/region/list/", #尾部多了个'/'
    	      "headers" : {
    	        "host" : "settings.bce-internal.baidu.com",
    	        "x-bce-date": "2017-02-15T08:52:48Z"
    	      }
    	    }
    	  }

    进而,IAM基于服务提供的请求信息,演算签名时URI与客户端不一致,得到的签名必然与请求值不一致。

    Host头域端口不一致

    客户端请求:

    	# 客户端请求的CanonicalRequest:
    	GET
    	/v1/settings/region/list
    	host:settings.bce-internal.baidu.com%3A80
    	x-bce-date:2017-02-15T08%3A52%3A48Z

    服务端向IAM构造验签请求时,host字段并没有加上端口:

    	{
    	  "auth" : {
    	    "authorization" : "bce-auth-v1/f3e1f5c2ef9c4d25b7f8b936861cd175/2017-04-05T08:29:50Z/3600/host;x-bce-date/2671990529b9c46c95e688f1a2809db185c608ee3716a731a8fdde6bb2028d84",
    	    "request" : {
    	      "method" : "GET",
    	      "uri" : "/v1/settings/region/list/",
    	      "headers" : {
    	        "host" : "settings.bce-internal.baidu.com", #host并没带端口
    	        "x-bce-date": "2017-02-15T08:52:48Z"
    	      }
    	    }
    	  }

    host不一致,得到的签名必然与请求值不一致。

    x-bce-date头的问题

    默认情况(authorization中未指明SignedHeaders时)x-bce-date会参与签名。客户端需要保证:计算签名时的此域,与最终发出请求时的此域,二者保持一致。

    如,计算签名时使用的时间是 2017-02-15T08:52:48Z

    	GET
    	/v1/settings/region/list
    	host:settings.bce-internal.baidu.com
    	x-bce-date:2017-02-15T08%3A52%3A48Z

    但发出请求时,x-bce-date 变成了 2017-02-15T08:52:49Z

    	GET /v1/settings/region/list HTTP/1.1
    	User-Agent: curl/7.33.0
    	Host: settings.bce-internal.baidu.com
    	Accept: */*
    	authorization: bce-auth-v1/f3e1f5c2ef9c4d25b7f8b936861cd175/2017-04-05T08:29:50Z/3600/host;x-bce-date;x-bce-request-id/9a48ec83ffb6c486892c4985df7dc6bc20f7c7bebb483f8f355592b8503a3f59
    	x-bce-date: 2017-02-15T08:52:49Z

    IAM演算签名时x-bce-date域与客户端不一致,得到的签名必然与请求值不一致。

    用错了ak/sk

    以下两种情况容易出现低级的错误导致签名不通过:

    • 基于配置的程序,配置中ak对了,但sk却存在错误。这种情况IAM并不会返回ak不存在,而是签名错误。一个特点是signningKey与IAM演算的不一致。
    • 自动从API拿到的ak/sk,但是构造业务client时却传错了,比如构造参数可能分别是ak和sk,但代码调用时两个参数都使用了ak。

    客户基于StsCredential来请求但服务未正确传递security_token

    客户端请求:

    # 客户端请求的CanonicalRequest:
    GET
    /v1/settings/region/list
    host:settings.bce-internal.baidu.com
    x-bce-date:2017-02-15T08%3A52%3A48Z
    x-bce-security-token: ZGZiM2M3MmU4Mjk4NGQ2MGEzYTNhYTAyMDE3NTZmZmV8AAAA...

    服务端向IAM构造验签请求时,没有将security_token提取出来,放到专门的字段,用于周知IAM客户使用了临时credential:

    {
      "auth" : {
        "authorization" : "bce-auth-v1/f3e1f5c2ef9c4d25b7f8b936861cd175/2017-04-05T08:29:50Z/3600/host;x-bce-date/9a48ec83ffb6c486892c4985df7dc6bc20f7c7bebb483f8f355592b8503a3f59",
        "request" : {
          "method" : "GET",
          "uri" : "/v1/settings/region/list",
          "headers" : {
            "host" : "settings.bce-internal.baidu.com",
            "x-bce-date": "2017-02-15T08:52:48Z",
            "x-bce-security-token": "ZGZiM2M3MmU4Mjk4NGQ2MGEzYTNhYTAyMDE3NTZmZmV8AAAA..."
          }
        }
      }

    IAM不知道签名为临时ak/sk签出,从长效ak/sk表中查找不到相应的ak,于是会报"Could not find credential"。

    生成签名过程中注意事项

    1. 检查HTTP Method是否正确
    2. CanonicalURI部分

      • 注意前面不需要加host,必须以“/”开头,不以“/”开头的需要补充上,空路径为“/”;
      • 注意结尾不该有“/”;
      • 注意要做uriEncodeExceptSlash编码。
    3. CanonicalQueryString部分

      • 注意要按字典序进行排序;
      • 没有value的key,是否也保留了“=”;
      • 没有queryString时,也要在最终的CanonicalRequest中拼接一个\n。
    4. CanonicalHeaders部分

      • 百度智能云默认的signedHeaders:Host、Content-Length、Content-Type、Content-MD5、所有以 x-bce- 开头的Header;
      • 注意这里的header内容,要与实际请求中的header内容完全一致,尤其注意host是否有端口号,x-bce-date是否有变化;
      • 实际发出请求中,是否有header被第三方库删除了?
      • 如果请求中{signedHeaders}字段留空,那么是否完全按照百度智能云默认的signedHeaders计算的?
    5. 签名前缀信息

      • timestamp是认证字符串创建时间,不能过早或过晚;
      • 输入的SK与AK要对应
    一篇
    Sample-Code
    一篇
    错误码