如何在Nextjs 13 App Router中计算请求的SHA-256校验和?

ax6ht2ek  于 2023-10-18  发布在  其他
关注(0)|答案(1)|浏览(97)

我在一个nextjs 13应用程序中有一个webhook,它使用了新的应用程序路由器。传入的lemon squeezy请求经过签名,并在x-signature报头中提供该签名。
根据他们的文档,签名必须从原始身体计算出来。我如何在应用路由器路由中访问它?
我尝试了这个,但它(显然)不会工作,因为它不处理原始数据,而是处理已解析的主体。(顺便说一下,传入的Request对象中的body对象是ReadableStream类型)

const isSignatureValid = (requestSignature: string | null, body: any) => {
  const secret = process.env.LMS_SECRET || "";
  const hmac = crypto.createHmac("sha256", secret);

  const calculatedHash = hmac.update(JSON.stringify(body)).digest("hex");
  console.log("found signature:", `[${requestSignature}]`);
  console.log("calculated hash:", `[${calculatedHash}]`);

  const digest = Buffer.from(calculatedHash, "utf8");
  const signature = Buffer.from(requestSignature || "", "utf8");

  return digest.length === signature.length && crypto.timingSafeEqual(digest, signature);
};
cx6n0qe3

cx6n0qe31#

解决了这个问题。我首先将Response对象的主体加载到Buffer中,该对象的类型为ReadableStream<Uint8Array>。我用了这个方法

async function toBuffer(stream: ReadableStream<Uint8Array>) {
  const list = [];
  const reader = stream.getReader();
  while (true) {
    const { value, done } = await reader.read();
    if (value) list.push(value);
    if (done) break;
  }
  return Buffer.concat(list);
}

我找到了here
完成此操作后,流将被消耗,您不能再使用req.json()方法。但是,你可以简单地toString() body,然后像这样解析json:

const b = await toBuffer(req.body!);

  const bString = b.toString();
  console.log("b.toString() 👇");
  console.log(bString);

  const bJson = JSON.parse(bString);
  console.log("JSON.parse(b.toString()) 👇");
  console.log(bJson);

相关问题