基于RFC 7515在JS中生成X-JWS-Signature:JWT不以ey开头排查
问题分析与修复方案
你的代码存在两个核心错误,导致生成的JWT无法以"ey"开头:
错误点1:Header未序列化就编码
你直接将header对象传入base64UrlEncode函数,此时data.toString('base64')会把对象转为字符串"[object Object]",编码结果完全不符合JWS要求。正确的做法是先将Header序列化为JSON字符串,再进行Base64URL编码。
错误点2:Base64URL编码逻辑错误
字符串的toString()方法不支持'base64'参数,只有Node.js的Buffer对象才有这个能力。你当前的编码逻辑无法正确将JSON字符串转为Base64格式,自然得不到JWT开头的"ey"("ey"是{"alg":"RS256","typ":"JWT"}的Base64URL编码前缀)。
修复后的代码
const crypto = require('crypto'); function signJson(json, privateKey) { const header = { alg: 'RS256', typ: 'JWT' }; // 先将Header和Payload序列化为JSON字符串,再编码 const encodedHeader = base64UrlEncode(JSON.stringify(header)); const encodedPayload = base64UrlEncode(JSON.stringify(json)); const data = encodedHeader + '.' + encodedPayload; // 签名结果需要转为Base64URL格式 const signature = crypto.createSign('RSA-SHA256') .update(data) .sign(privateKey, 'base64') .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/, ''); return data + '.' + signature; } function base64UrlEncode(data) { // 先将输入转为Buffer,再执行Base64编码和字符替换 return Buffer.from(data).toString('base64') .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/, ''); }
关键修复说明
- 对Header执行
JSON.stringify(),确保编码的是标准JSON字符串 - 重写
base64UrlEncode函数,用Buffer.from(data)将输入转为Buffer后再做Base64编码 - 签名结果也需要转为Base64URL格式(
crypto.sign返回的是普通Base64,需替换字符并移除末尾等号)
内容的提问来源于stack exchange,提问作者MatnikR
相关产品推荐
相关产品推荐

