生成 JWT 表单头和有效负载
Posted
技术标签:
【中文标题】生成 JWT 表单头和有效负载【英文标题】:Generate JWT form header and payload 【发布时间】:2020-08-26 03:21:11 【问题描述】:我正在使用 node js 在我的后端服务器中创建一个 jwt。 我正在使用库来签名/验证 JWT,它工作正常。一旦一个 jwt.io 我粘贴了我登录时获得的令牌,我就可以在有效负载中看到我的数据。 所以问题是我正在尝试从标头和我在 jwt.io 中返回的有效负载生成签名 这是我试图做的,但它不起作用,我有点困惑。 用于签名的算法是默认的HS256。
const crypto = require("crypto");
// encode base64 the header
let jsonHeader = JSON.stringify(
alg: "HS256",
typ: "JWT",
);
let bs64header = Buffer.from(jsonHeader).toString("base64").split("=")[0];
console.log("bs64header :>>\n ", bs64header); //look the same as the token i got
// encode vase64 the payload
let jsonPayload = JSON.stringify(
id: "5eb20004ac94962628c68b91",
iat: 1589125343,
exp: 1589989343,
jti: "37743739b1476caa18ca899c7bc934e1aba63ba1",
);
let bs64payload = Buffer.from(jsonPayload).toString("base64").split("=")[0];
console.log("bs64Payload :>> \n", bs64payload); //look the same as the token i got
// TRY to generate the signature from the Base64Header and Base64Payload
// with the secret code that i used to sign the JWT
let secret = "0d528cb666023eee0d44e725fe9dfb751263d2f68f07998ae7388ff43b1b504f";
let signature = bs64header + "." + bs64payload;
let hashed = crypto
.createHash("sha256", secret)
.update(signature)
.digest("hex");
console.log("hashed :>> \n", hashed);
let bs64signature = Buffer.from(hashed).toString("base64").split("=")[0];
console.log("bs64signature>>", bs64signature); //This is where i got stuck.
// let jwt = bs64header + "." + bs64payload + "." + bs64signature;
// console.log("jwt>>", jwt);
【问题讨论】:
为什么要自己生成jwt字符串??我想您需要查看npmjs.com/package/jsonwebtoken。这将大大减少您的代码以及您为创建令牌所做的所有手动步骤。令牌非常敏感,结构上的一个错误,您将无法验证或读取它。 我使用 jwt.sign() 创建令牌并使用 jwt.verify() 检查令牌是否良好。但是当我想为用户创建一个注销根时,这两种方法并不安全。所以我需要在 Payload 中使用一些自定义声明创建自己的令牌,以便稍后进行一些验证! 您可以在通过 JSONWebToken 库创建令牌时添加自定义声明。这些方法不安全的事实到底是什么意思?你可以在你的令牌中提供一个角色范围来检查它是什么类型的用户。 其实我是我的错,没有对 JWT 做更多的研究并试图理解它。我也同意你的第一条评论,使用 npmjs.com/package/jsonwebtoken 也会更有用。但这是一个很好的练习,有助于更好地了解 JWT 的工作原理以及如何自己制作。 【参考方案1】:我已经对您的代码进行了很多修改,以减少重复性并且更易于阅读。我不完全确定这是否会起作用,所以如果有任何错误,请发表评论。
我已经在runkit 中对其进行了测试,并且还检查了应该使用jwt.io 的输出。输出看起来是一样的,所以我很确定这是可行的。
变化
创建了一个函数来base64对对象和字符串进行编码。 创建了一个函数以使 base64 字符串使用 URL 安全字符集。 将crypto.createHash()
更改为crypto.createHmac()
,以便实际使用密钥。
// base64 encode the data
function bs64encode(data)
if (typeof data === "object")
data = JSON.stringify(data);
return bs64escape(Buffer.from(data).toString("base64"));
// modify the base64 string to be URL safe
function bs64escape(string)
return string.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
// base64 encode the header
let bs64header = bs64encode(
alg: "HS256",
typ: "JWT"
);
console.log("bs64header :>>\n ", bs64header);
// base64 encode the payload
let bs64payload = bs64encode(
id: "5eb20004ac94962628c68b91",
iat: 1589125343,
exp: 1589989343,
jti: "37743739b1476caa18ca899c7bc934e1aba63ba1"
);
console.log("bs64payload :>> \n", bs64payload);
// generate the signature from the header and payload
let secret = "0d528cb666023eee0d44e725fe9dfb751263d2f68f07998ae7388ff43b1b504f";
let signature = bs64header + "." + bs64payload;
let bs64signature = bs64escape(crypto
.createHmac("sha256", secret)
.update(signature)
.digest("base64"));
console.log("bs64signature>>", bs64signature);
let jwt = bs64header + "." + bs64payload + "." + bs64signature;
console.log("jwt>>", jwt);
【讨论】:
谢谢!!这工作也是。在检查您的答案之前,我也是一个解决方案。所以我缺少的是这个 - 创建了一个函数来使 base64 字符串使用 URL 安全字符集。 - 将 crypto.createHash() 更改为 crypto.createHmac(),以便实际使用密钥。以上是关于生成 JWT 表单头和有效负载的主要内容,如果未能解决你的问题,请参考以下文章