You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Alexa技能部署至Cloud Functions时含额外属性JSON请求被拒

问题根因

报错和ask-sdk-core版本更新无关,核心是签名校验的入参处理逻辑不符合Alexa的验签规则:

  • Alexa签名校验要求必须使用HTTP请求的原始未修改payload做哈希比对,任何对请求体的重新序列化、字段顺序调整、内容改动都会导致签名不匹配
  • 你当前代码没有获取原始请求体,而是将express解析后生成的JS对象req.body通过JSON.stringify重新序列化作为验签入参
  • JSON标准不约束对象键的排序规则,当Alexa在请求中新增属性、或express解析后键顺序和原始请求不一致时,重新生成的序列化字符串和Alexa侧用来生成签名的原始文本完全不同,就会抛出request body and signature does not match错误
  • 其他同代码服务器可正常运行属于偶发兼容:老版本express/body-parser的序列化键顺序刚好和原始请求一致,不代表逻辑正确,遇到新增字段就会触发故障。
修复方案

核心是在express解析请求体时保留原始raw body,验签直接使用原始body,不要自行序列化。

代码调整

修改server.js

配置express的json解析中间件,在解析的同时缓存原始请求buffer:

const skillRoute = require("./skill");
const express = require("express");
const server = express();

// 解析JSON请求体,同时保留原始raw body用于验签
server.use(express.json({
  verify: (req, res, buf, encoding) => {
    req.rawBody = buf;
  }
}));

server.use("/", skillRoute);
exports.server = functions.https.onRequest(server);

修改skill.js

将验签逻辑的入参替换为缓存的原始请求体,移除手动序列化的逻辑:

// imports here...
Router.post("/:locale", async (req, res) => {
  try {
    // 直接使用原始请求buffer做验签
    await new SkillRequestSignatureVerifier().verify(req.rawBody, req.headers);
    await new TimestampVerifier().verify(req.rawBody);
  } catch (err) {
    console.log(`Error with message: ${err.message}`);
    console.log(`Error object: ${JSON.stringify(err)}`);
    return res.status(400).send(err.message);
  }
  const responseASK = await skill.invoke(req.body);
  return res.status(200).send(responseASK);
});

module.exports = Router;
合规验证说明

修改完成后,无论Alexa后续在请求JSON中新增多少未知属性,验签使用的都是和Alexa侧完全一致的原始请求文本,不会再触发签名错误;同时ASK SDK本身默认支持忽略未知JSON属性,完全满足Alexa技能发布的向后兼容性要求。


内容的提问来源于stack exchange,提问作者Exlley Santos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 10:03:21