新闻中心
解决Webhook签名验证中Python与TypeScript差异的实用指南

本文旨在解决在Webhook签名验证过程中,Python与TypeScript实现之间出现的差异问题。通过详细分析两种语言在JSON序列化时的不同行为,提供了一套可靠的TypeScript解决方案,确保签名验证的一致性和准确性。该方案通过规范化JSON字符串格式,消除了因空格差异导致的验证失败问题,从而保证了Webhook通信的安全性和可靠性。
在开发涉及Webhook的应用时,确保接收到的数据确实来自可信来源至关重要。Webhook签名验证是一种常见的安全措施,它通过使用共享密钥对请求内容进行签名,并在接收端验证签名,从而防止恶意篡改。然而,在跨语言环境中实现签名验证时,可能会遇到一些意想不到的问题,例如Python和TypeScript在处理JSON序列化时的差异。
问题根源:JSON序列化格式的差异
Python的json.dumps()方法在默认情况下会生成紧凑的JSON字符串,不包含额外的空格。而TypeScript中使用JSON.stringify()在没有指定参数的情况下也会生成紧凑的JSON字符串。但是,如果格式化JSON(例如为了方便调试),可能会引入空格,导致生成的签名与预期不符。即使没有格式化,不同的JSON序列化库也可能在空格处理上存在细微差异。
解决方案:规范化JSON字符串格式
为了解决这个问题,我们需要在TypeScript中规范化JSON字符串的格式,使其与Python生成的格式保持一致。一种有效的方法是使用一系列的字符串替换操作,移除或调整JSON字符串中的空格。
以下代码展示了如何使用Ramda库中的pipe和replace函数,创建一个名为toJSONWithSpaces的函数,该函数可以规范化JSON字符串的格式:
Visla
AI视频生成器,快速轻松地将您的想法转化为视觉上令人惊叹的视频。
100
查看详情
import { pipe, replace } from 'ramda';
export const toJSONWithSpaces = pipe(
(object: unknown) => JSON.stringify(object, null, 1), // stringify with line-breaks and indents
replace(/\n +/gm, ' '), // replace line breaks and following spaces with a single space
replace(/:\s/g, ': '), // ensure a space after colon
replace(/{\s/g, '{'), // remove space after opening brace
replace(/\s}/g, '}'), // remove space before closing brace
replace(/\[\s/g, '['), // remove space after opening bracket
replace(/\s]/g, ']'), // remove space before closing bracket
replace(/,\s/g, ', '), // ensure a space after comma
);这个函数首先使用JSON.stringify(object, null, 1)将对象转换为带有换行符和缩进的JSON字符串。然后,它使用一系列的正则表达式替换操作来移除或调整空格,以确保JSON字符串的格式与Python生成的格式一致。
集成到签名验证函数中
接下来,我们需要将toJSONWithSpaces函数集成到签名验证函数中。以下是一个修改后的verifyCloseSignature函数,它使用toJSONWithSpaces函数来规范化payload:
import { toJSONWithSpaces } from './json-formatter'; // 假设 toJSONWithSpaces 函数在 json-formatter.ts 文件中
import * as crypto from 'crypto';
export function verifyCloseSignature(
request: Request,
key: string,
payload: any,
) {
const headers = request.headers;
const timestamp = headers.get('close-sig-timestamp');
const providedSignature = headers.get('close-sig-hash');
if (!timestamp) {
throw new Error('[verifyCloseSignature] Required timestamp header missing');
}
if (!providedSignature) {
throw new Error('[verifyCloseSignature] Required signature header missing');
}
const hmac = crypto.createHmac('sha256', Buffer.from(key, 'hex'));
const cleanedPayload = toJSONWithSpaces(payload);
hmac.update(timestamp + cleanedPayload);
const calculatedSignature = hmac.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(providedSignature, 'hex'),
Buffer.from(calculated
Signature, 'hex'),
);
}在这个修改后的函数中,我们首先使用toJSONWithSpaces(payload)来规范化payload,然后再将其用于HMAC计算。
注意事项
- 依赖管理: 确保安装了ramda库,可以通过运行npm install ramda或yarn add ramda来安装。
- 密钥格式: 确认密钥是以十六进制字符串的形式提供的,并且在TypeScript中使用Buffer.from(key, 'hex')正确地将其转换为Buffer。
- 时间戳: 确保时间戳的格式在Python和TypeScript中一致。通常,时间戳应该是一个整数或字符串,表示自Epoch以来的秒数。
- Content-Type: 确保请求头的 Content-Type 设置为 application/json。
总结
通过规范化JSON字符串的格式,我们可以解决在Webhook签名验证过程中Python和TypeScript实现之间的差异问题。这种方法可以确保签名验证的一致性和准确性,从而提高Webhook通信的安全性和可靠性。在实际应用中,建议编写单元测试来验证签名验证函数的正确性,并定期审查和更新代码,以应对潜在的安全风险。
以上就是解决Webhook签名验证中Python与TypeScript差异的实用指南的详细内容,更多请关注其它相关文章!
# 转换为
# 海口网站建设的重要步骤
# 南京营销推广厂家
# 永川区品牌网站建设公司
# 邢台网站推广引流
# 徐元seo图片
# 商洛抖音seo运营公司
# 宜昌平台网站建设
# seo网站优化自学
# 大兴营销网络推广
# 网站平台建立与推广
# 情况下
# 您的
# 复用
# 过程中
# 移除
# python
# 将其
# 序列化
# 是一个
# cryp
# red
# win
# amd
# mac
# app
# npm
# typescript
# 正则表达式
# json
# js
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
J*aScript数组对象转换:按指定键分组与值收集
Yandex官网免登录入口_俄罗斯Yandex搜索引擎一键访问
Go语言中动态执行代码字符串的策略与实践
2026春节假期票务安排_2026春节放假购票指南
mysql如何设置表访问权限_mysql表访问权限配置
PySpark中高效提取字符串右侧可变长度数字:使用regexp_extract
抓大鹅解压小游戏 抓大鹅摸鱼解压入口
《噬血代码2》新预告片发布 展示游戏剧情
《燕云十六声》两周内达九百万玩家!位居畅销榜第五
UC浏览器官网入口2025最新 UC浏览器网页版正式地址
腾讯视频怎么使用多账号家庭管理_腾讯视频家庭多账号统一管理与权限分配教程
Yandex搜索引擎官网入口_俄罗斯Yandex免登录一键直达
sublime如何优雅地处理行尾空格_sublime自动清理多余空白字符配置
深入理解字体排版:Adobe光学字偶距与CSS字偶距的差异与实现
Google翻译怎么语音输入_Google翻译语音输入功能使用与设置方法
PDF怎么合并PDF并保持格式_PDF合并文件保持排版教程
如何在网页中实现特定地点的随机图片展示
从J*aScript对象中精确提取指定属性的教程
正确连接J*aScript到HTML实现可点击图片与自定义事件处理
sublime侧边栏怎么增强功能_SideBarEnhancements for sublime安装与配置
向日葵客户端怎么进行远程CentOS控制_向日葵客户端远程CentOS控制操作教程
在J*a中如何开发简易仓库管理与库存统计_仓库管理库存统计项目实战解析
如何在CSS中使用浮动制作导航栏_float实现水平菜单
c++ dfs和bfs代码 c++深度广度优先搜索算法
淘宝支付提示失败如何解决 淘宝支付流程优化方法
J*aScript DOM操作:高效清空列表元素的策略与实践
如何高效处理PHP中的Excel数据导入导出?PortPHP/Spreadsheet助你轻松搞定!
京东单号查询入口_京东快递订单追踪入口
composer的"require-dev"部分是用来做什么的?
俄罗斯Yandex搜索引擎入口_Yandex官网免登录一键访问
Win11蓝牙耳机断连怎么解决 Win11蓝牙设置重新配对与驱动更新【技巧】
AO3镜像入口大全 AO3网页版内容访问全集
NVIDIA股价11月重挫12%:下月有望好转 但难回5万亿美元巅峰
C++编译期如何执行复杂计算_C++模板元编程(TMP)技巧与应用
照顾宝贝2小游戏点击立即在线玩
sublime怎么覆盖插件的默认快捷键_sublime快捷键优先级与设置
Win11怎么开启省电模式_Win11电池节电模式自动开启
文心一言怎样用批量生成做多版文案_文心一言用批量生成做多版文案【批量创作】
Golang如何使用new_Go new分配内存机制讲解
Lar*el 递归关系中排除指定分支的教程
天眼查怎么看公司融资情况 天眼查企业融资历史查询步骤【攻略】
AO3最新镜像入口 Archive of Our Own官方平台访问
J*aScript map 迭代中检测空数组元素的有效方法
解决 Vaadin 8 中大文件音频播放与定位时出现的 IOException
Lar*el Excel导入时生成自定义递增ID的策略与实践
汽水音乐在线解析 汽水音乐在线解析入口
AO3最新入口2025公告_AO3中文官网合集
《北京人工智能产业白皮书(2025)》发布:全年核心产值预计突破 4500 亿元
漫蛙2网页版漫画入口 漫蛙漫画在线官方登录
HTML元素状态管理:根据DIV内容动态启用/禁用按钮


2025-11-15
浏览次数:次
返回列表
Signature, 'hex'),
);
}