签署请求和时间戳

Signing Requests & Timestamps

亚马逊有一个方便的花花公子工具,用于测试请求并确认您正在正确签署请求,他们称之为 'scratchpad'。你递给它一个未签名的请求,输入你的身份验证信息,点击提交,它会吐出一个签名的请求。要么它要么我的代码坏了,逻辑表明这是我的代码,但这没有任何意义。也许这里有人可以看到我没有看到的东西。

如果我向暂存器提交一个未签名的请求,例如

http://webservices.amazon.com/onca/xml?AWSAccessKeyId=ME&AssociateTag=ME&Keywords=bbq&Operation=ItemSearch&ResponseGroup=ItemAttributes&SearchIndex=All&Service=AWSECommerceService

我回来了

http://webservices.amazon.com/onca/xml?AWSAccessKeyId=ME&AssociateTag=ME&Keywords=bbq&Operation=ItemSearch&ResponseGroup=ItemAttributes&SearchIndex=All&Service=AWSECommerceService&Timestamp=2017-07-16T15%3A14%3A09.000Z&Signature=4oLDpXEdZ%2BEEPBOOPIMAROBOTiALFPPeICbs%3D

如果我向 URL 发出请求( 我从 AMZN 的工具 获得),我得到

Value 2017-07-16T15%3A14%3A09.000Z for parameter Timestamp is invalid. Reason: Must be in ISO8601 format.

如果我手动取消 url 将时间戳编码为 2017-07-16T15:14:09.000Z 那么它似乎已经过去了,只是失败了可怕的 SignatureDoesNotMatch.

但是

如果我使用上面签名的 url 中的查询字符串和 url 编码的时间戳 创建自己的签名消息,则签名匹配!这意味着他们的后端正在使用 url 编码的时间戳来计算签名,但我提出的任何带有时间戳的请求,无论是否 url 编码,都会给我 "that's not iso8601" 错误。所有 url 编码所做的就是用 %3A 代替 : - 这不是一个复杂的过程。

我已经确认 运行 服务器的语言环境是 utf-8,并且我也使用 application/x-www-form-urlencoded; charset=utf-8 作为请求的内容类型确认系统时钟与权威 ntp 服务器同步。

希望有人以前看过这个或类似的东西。

Drakma客户端自动对参数进行url编码,轮流编码两次。即使您不将它们作为参数列表传递,而是直接在 uri 中传递,它也会对参数进行编码。为了保持 URI 不变,您必须使用 :preserve-uri t,如文档中所述:

If preserve-uri is not NIL, the given uri will not be processed. This means that the uri will be sent as-is to the remote server and it is the responsibility of the client to make sure that all parameters are encoded properly. Note that if this parameter is given, and the request is not a POST with a content-type of `multipart/form-data', parameters will not be used.