mturk API 大约有一半时间给出 "specified claims are invalid" 消息;重新提交随机修复

mturk API gives "specified claims are invalid" message about half the time; resubmitting randomly fixes

我正在使用自定义 PHP 脚本根据 the PHP-AWS library 中的签名函数向 mturk API 提交请求。下面是一个请求示例:

https://mechanicalturk.amazonaws.com/?Service=AWSMechanicalTurkRequester&AWSAccessKeyId=MYKEY&Version=2012-03-25&Operation=NotifyWorkers&Signature=j+4UTX9x3EKltvWpoxIkp4BM6S4=&Timestamp=2015-06-25T09:37:51Z&Subject=test&MessageText=just+testing+&WorkerId.1=SOMEID

有时给定的脚本会起作用,而在其他时候,同一个脚本会 return 出现这样的错误:

AWS.BadClaimsSupplied The specified claims are invalid. Based on your request, your signature should be generated using the following string: AWSMechanicalTurkRequesterNotifyWorkers2015-06-25T09:37:51Z. Check to make sure your system clock and timezone is not incorrect. Our current system time: 2015-06-25T09:37:51Z. (1435225071849)

当我收到 AWS.BadClaimsSupplied 错误时,反复重新运行该脚本会使它最终起作用。 "work," 我的意思是 API returns true 并且采取了所需的操作,或者 returns 是与我的操作相关的错误我请求。

我假设如果我不正确地执行散列或使用错误的签名,那么它永远不会工作*。问题的间歇性使我认为这是一个时间错误。但是上面的示例显示了一条错误消息,其中我用于签名的时间与他们的时间相同,因此这似乎也不是问题。

*好的,每尝试 2^160 次就会成功一次。

我尝试将我的时间戳回溯 1 秒,以防我比他们早一点;那并没有改变结果。我想不出任何其他方法来调试它。

错误消息听起来好像问题出在被散列的字符串上,但实际问题是一些散列的字符串包含特殊字符。字符 +/= 会影响 URL 的解析方式,并且会干扰阅读您的签名。使用不同的时间字符串重新运行请求将随机return一个没有这些字符的散列,允许请求工作。

解决方案:在进行 API 调用之前,只需在签名上 运行 urlencode()。如果出于某种原因您不想这样做,this answer 提供了一些仅对那些特定字符进行编码的代码,但我认为标准功能更全面、更安全。