API网关排序查询字符串

Tim*_*cht 4 node.js express aws-lambda aws-api-gateway serverless-framework

我目前正在尝试使用 API Gateway + Lambda 上的无服务器框架来实现 Express 应用程序。一切都按预期进行,直到我开始在我们这边引入请求签名。签名的工作方式是使用秘密令牌对包含查询字符串的完整 URL 进行签名。不幸的是,API Gateway 或 Cloudfront 似乎都按字母顺序重新排序查询字符串,这导致我们这边生成的校验和与客户端生成的校验和不同。

我们的 Express 服务器看到的内容:

https://example.com/endpoint?build_number=1&platform=ios

客户发送的内容:

https://example.com/endpoint?platform=ios &build_number=1

正如您所看到的,查询参数按字母顺序重新排序,这不是我所期望的行为。

任何想法?

Mic*_*bot 5

我建议您的算法注定会给您带来问题,因为查询字符串是一组没有内在排序的键/值对。

不应期望它会以任何特定顺序通过任何特定系统。请求标头也是如此。一些构建 HTTP 请求的库将查询字符串参数存储在中间字典/哈希结构中,因此即使没有您在这里看到的问题(我怀疑是 API 网关,因为 CloudFront 声称保留顺序),这可以说是一个子问题最佳设计因为?color=red&size=large(再次,可以说,但非常引人注目)与完全相同?size=large&color=red

我的猜测是,API Gateway 可能通过规范化查询字符串排序来优化其执行缓存的能力(实际上并不使用 CloudFront 缓存——它有自己的实现)。

但是,正如我上面所建议的,您的算法应该需要对发送端的查询参数进行二进制、词法排序(区分大小写,而不是可能被认为不区分大小写的“字母顺序”),并且在接收端再次进行相同的操作结尾。

这似乎是不必要的复杂性,但这几乎可以肯定是为什么各种AWS签名算法要求在签名之前对查询字符串(和标头,出于同样的原因)键和值进行排序——因为你根本不能依赖客户端库,代理或其他实体来一致地处理它们。