常见签名认证错误排查
所有文档
menu

相关参考 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
下一篇
错误码