构造SQS SendMessage REST请求遇SignatureDoesNotMatch错误
解决SQS SendMessage请求含空格时的403 SignatureDoesNotMatch错误
这个问题我之前碰到过类似的,核心原因就是签名计算时使用的请求体内容,和实际发送给SQS的请求体内容不完全一致,导致哈希校验失败,触发了403错误。咱们一步步拆解问题和解决方法:
关键原理:AWS签名的核心要求
AWS的V4签名机制中,会对请求的多个部分计算哈希,其中就包括完整的请求体内容。只有当签名时计算的请求体哈希,和SQS收到的实际请求体哈希完全匹配,签名才会通过。
你的问题出在哪?
当MessageBody是纯无空格字符串(比如"HelloWorld")时,URL编码前后内容一致,所以签名计算和实际发送的请求体没有差异,请求正常。但当有空格时,两种错误情况都会导致签名不匹配:
- 签名时用了原始的"Hello World"(未URL编码),但实际发送时把空格转成了"%20",导致请求体内容不一致;
- 签名时对MessageBody做了URL编码(用"Hello%20World"),但实际发送时又用了原始的"Hello World",同样导致哈希不匹配。
正确的处理步骤
1. 按规则构造请求体(application/x-www-form-urlencoded格式)
SQS的POST类型REST请求,要求请求体是标准的表单编码格式:
- 每个参数的值必须做URL编码(包括MessageBody、QueueUrl、Action);
- 参数之间用
&分隔,格式为key1=encoded_value1&key2=encoded_value2。
比如,当MessageBody是"Hello World"时,正确的请求体应该是:
QueueUrl=https%3A%2F%2Fsqs.us-east-1.amazonaws.com%2F123456789012%2FMyQueue&Action=SendMessage&MessageBody=Hello%20World
2. 用编码后的完整请求体计算签名
在生成V4签名的过程中,计算请求体哈希时,必须使用上面这个完整的、编码后的请求体字符串,而不是原始的未编码内容。
3. 确保实际发送的请求和签名时的内容完全一致
- 发送请求时,请求头必须设置
Content-Type: application/x-www-form-urlencoded; - 发送的请求体必须和签名计算时用的字符串完全相同,不能有任何字符差异(包括空格、编码字符的大小写等)。
额外检查点
- 确认签名计算时的Canonical Request中,
Content-Type头已经被包含在Signed Headers列表里,并且值正确; - 所有字符串处理都使用UTF-8编码(AWS要求统一用UTF-8),避免因编码格式不同导致的字节差异;
- 检查是否在签名计算过程中,不小心对请求体做了额外的转义或截断。
按照这个流程调整后,带空格的MessageBody应该就能正常通过签名校验了。
内容的提问来源于stack exchange,提问作者lostintranslation
相关产品推荐
相关产品推荐

