API网关排序查询字符串

4
我目前正在尝试使用Serverless框架在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 可以看到,查询参数被重新按字母顺序排列,这不是我所希望的行为。
有什么想法吗?
1个回答

5
我建议您的算法注定会出现问题,因为查询字符串是一组没有固有顺序的键/值对。不应该期望它以任何特定的顺序通过任何特定的系统。请求头也是如此。一些构建HTTP请求的库将查询字符串参数存储在中间字典/哈希结构中,因此即使没有您在此处看到的问题(我怀疑是API Gateway,因为CloudFront声称保留排序),这可能是一个次优设计,因为?color=red&size=large?size=large&color=red(再次强调,但是非常有说服力)完全相同
我猜测API Gateway可能正在通过规范化查询字符串顺序来优化其执行缓存的能力(实际上并不使用CloudFront缓存--它有自己的实现)。

但是,正如我上面所建议的那样,您的算法应该要求在发送端和接收端对查询参数进行二进制、词汇排序(区分大小写,而不是“字母顺序”,这可能被认为是不区分大小写的)。

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


1
完美的答案。 - jackko
我理解了答案的精髓。我发现很恼人的是,他们至少没有给您上下文属性或某种获取原始查询字符串的方法。在我的情况下,我正在编写一个模拟api,该api基于属性对请求进行哈希处理,包括查询字符串。因此,我现在要么返回并重新对所有内容进行哈希处理,以按照api网关的方式对查询字符串参数进行排序,要么计算每个排列以找到正确的哈希值。 - brendonparker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接