如何使用 JavaScript 解码 JWT 的有效负载?没有图书馆。所以令牌只返回一个可以被我的前端应用程序使用的有效负载对象。
示例令牌:xxxxxxxxx.XXXXXXXX.xxxxxxxx
结果是有效载荷:
{exp: 10012016 name: john doe, scope:['admin']}
注意:这不会验证签名,它只是从令牌中提取 JSON 有效负载,这可能已被篡改。
浏览器
工作 unicode 文本 JWT 解析器功能:
function parseJwt (token) {
var base64Url = token.split('.')[1];
var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
var jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
return JSON.parse(jsonPayload);
};
JWT 使用 base64url
(RFC 4648 §5),因此仅使用 atob
(使用 base64
)是不够的。
节点.js
function parseJwt (token) {
return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
}
简单的try-catch函数
const parseJwt = (token) => {
try {
return JSON.parse(atob(token.split('.')[1]));
} catch (e) {
return null;
}
};
谢谢!
atob
知道 unicode problems
您可以使用 jwt-decode,因此您可以编写:
import jwt_decode from 'jwt-decode';
var token = 'eyJ0eXAiO.../// jwt token';
var decoded = jwt_decode(token);
console.log(decoded);
/*{exp: 10012016 name: john doe, scope:['admin']}*/
您可以使用纯 javascript atob()
函数将令牌解码为字符串:
atob(token.split('.')[1]);
或者直接解析成一个json对象:
JSON.parse(atob(token.split('.')[1]));
了解 atob()
和 btoa()
内置 javascript 函数Base64 encoding and decoding - Web APIs | MDN。
function parseJwt(token) {
var base64Payload = token.split('.')[1];
var payload = Buffer.from(base64Payload, 'base64');
return JSON.parse(payload.toString());
}
let payload= parseJwt("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c");
console.log("payload:- ", payload);
如果使用节点,您可能必须使用缓冲包:
npm install buffer
var Buffer = require('buffer/').Buffer
atob
,因为它已被弃用。
Buffer
不存在(您的框架可能会添加一个大的 polyfill),而 atob
仅在 Node.js 上被弃用,在浏览器中使用非常好。
由于 nodejs 环境中不存在“window”对象,我们可以使用以下代码行:
let base64Url = token.split('.')[1]; // token you get
let base64 = base64Url.replace('-', '+').replace('_', '/');
let decodedData = JSON.parse(Buffer.from(base64, 'base64').toString('binary'));
它完美地为我工作。希望能帮助到你。
.toString('binary')
?如果令牌中有特殊字符,这对我来说会很麻烦......虽然使用 .toString()
有效......
如果您使用的是 Typescript 或 vanilla JavaScript,那么这是一个零依赖,可以复制粘贴到您的项目简单函数中(基于 @Rajan Maharjan 的回答)。
这个答案特别好,不仅因为它不依赖于任何 npm 模块,还因为它不依赖于这里的一些其他解决方案正在使用的任何 node.js 内置模块(如Buffer
),当然会在浏览器中失败(除非 polyfill,但首先没有理由这样做)。此外 JSON.parse 可能在运行时失败,这个版本(尤其是在 Typescript 中)将强制处理。 JSDoc 注释将使您的代码的未来维护者心存感激。 :)
/**
* Returns a JS object representation of a Javascript Web Token from its common encoded
* string form.
*
* @template T the expected shape of the parsed token
* @param {string} token a Javascript Web Token in base64 encoded, `.` separated form
* @returns {(T | undefined)} an object-representation of the token
* or undefined if parsing failed
*/
export function getParsedJwt<T extends object = { [k: string]: string | number }>(
token: string,
): T | undefined {
try {
return JSON.parse(atob(token.split('.')[1]))
} catch {
return undefined
}
}
为了完成,这里也是 vanilla javascript 版本:
/**
* Returns a JS object representation of a Javascript Web Token from its common encoded
* string form.
*
* @param {string} token a Javascript Web Token in base64 encoded, `.` separated form
* @returns {(object | undefined)} an object-representation of the token
* or undefined if parsing failed
*/
export function getParsedJwt(token) {
try {
return JSON.parse(atob(token.split('.')[1]))
} catch (error) {
return undefined
}
}
atob
,它不是 Javascript 的一部分,而是一个 Web API。支持还不错,浏览器都支持。 Node 从 v16 开始支持它(这意味着当前有运行 Node 14 的主机,例如 AWS Lambda,它不支持它)。
如果您使用 Node.JS,您可以通过执行以下操作来使用本机 Buffer 模块:
const token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImp0aSI6ImU3YjQ0Mjc4LTZlZDYtNDJlZC05MTZmLWFjZDQzNzhkM2U0YSIsImlhdCI6MTU5NTg3NzUxOCwiZXhwIjoxNTk1ODgxMTE4fQ.WXyDlDMMSJAjOFF9oAU9JrRHg2wio-WolWAkAaY3kg4';
const tokenDecodablePart = token.split('.')[1];
const decoded = Buffer.from(tokenDecodablePart, 'base64').toString();
console.log(decoded)
你很高兴去:-)
JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString())
以直接获取 JS 对象。
@Peheje 会工作,但你会遇到 unicode 问题。为了修复它,我使用 https://stackoverflow.com/a/30106551/5277071 上的代码;
让 b64DecodeUnicode = str => decodeURIComponent( Array.prototype.map.call(atob(str), c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2 ) ).join('')) 让 parseJwt = token => JSON.parse( b64DecodeUnicode( token.split('.')[1].replace('-', '+').replace('_', '/') ) ) 让 form = document.getElementById("form") form.addEventListener("submit", (e) => { form.out.value = JSON.stringify( parseJwt(form.jwt.value) ) e.preventDefault(); }) textarea{width:300px;高度:60px; display:block}
我使用此函数根据 this 答案获取 payload 、 header 、 exp(Expiration Time)、 iat (Issued At)
function parseJwt(token) {
try {
// Get Token Header
const base64HeaderUrl = token.split('.')[0];
const base64Header = base64HeaderUrl.replace('-', '+').replace('_', '/');
const headerData = JSON.parse(window.atob(base64Header));
// Get Token payload and date's
const base64Url = token.split('.')[1];
const base64 = base64Url.replace('-', '+').replace('_', '/');
const dataJWT = JSON.parse(window.atob(base64));
dataJWT.header = headerData;
// TODO: add expiration at check ...
return dataJWT;
} catch (err) {
return false;
}
}
const jwtDecoded = parseJwt('YOUR_TOKEN') ;
if(jwtDecoded)
{
console.log(jwtDecoded)
}
我在 jwt.io 找到了这段代码,它运行良好。
//this is used to parse base64
function url_base64_decode(str) {
var output = str.replace(/-/g, '+').replace(/_/g, '/');
switch (output.length % 4) {
case 0:
break;
case 2:
output += '==';
break;
case 3:
output += '=';
break;
default:
throw 'Illegal base64url string!';
}
var result = window.atob(output); //polifyll https://github.com/davidchambers/Base64.js
try{
return decodeURIComponent(escape(result));
} catch (err) {
return result;
}
}
在某些情况下(某些开发平台),
the best answer(for now) 面临 base64 长度无效的问题。
所以,我需要一种更稳定的方法。
我希望它会帮助你。
如果使用 node.js 16 或更高版本,您可以使用内置的 base64url
编码器/解码器。
let payload = JSON.parse(Buffer.from(token.split(".")[1], "base64url"));
您可以定义和使用这一个线性函数:
jwtDecode = b => JSON.parse(Buffer.from(b.split('.')[1], 'base64').toString('binary'));
jwt.io 的所有功能不支持所有语言。在 NodeJs 中,您可以使用
var decoded = jwt.decode(token);
基于来自 GitHub - auth0/jwt-decode 的答案。更改了输入/输出以包括字符串拆分和返回对象 { header, payload, signature },这样您就可以传递整个令牌。
var jwtDecode = function (jwt) {
function b64DecodeUnicode(str) {
return decodeURIComponent(atob(str).replace(/(.)/g, function (m, p) {
var code = p.charCodeAt(0).toString(16).toUpperCase();
if (code.length < 2) {
code = '0' + code;
}
return '%' + code;
}));
}
function decode(str) {
var output = str.replace(/-/g, "+").replace(/_/g, "/");
switch (output.length % 4) {
case 0:
break;
case 2:
output += "==";
break;
case 3:
output += "=";
break;
default:
throw "Illegal base64url string!";
}
try {
return b64DecodeUnicode(output);
} catch (err) {
return atob(output);
}
}
var jwtArray = jwt.split('.');
return {
header: decode(jwtArray[0]),
payload: decode(jwtArray[1]),
signature: decode(jwtArray[2])
};
};
用于解码 JSON Web 令牌 (JWT) 的简单 NodeJS 解决方案
function decodeTokenComponent(value) {
const buff = new Buffer(value, 'base64')
const text = buff.toString('ascii')
return JSON.parse(text)
}
const token = 'xxxxxxxxx.XXXXXXXX.xxxxxxxx'
const [headerEncoded, payloadEncoded, signature] = token.split('.')
const [header, payload] = [headerEncoded, payloadEncoded].map(decodeTokenComponent)
console.log(`header: ${header}`)
console.log(`payload: ${payload}`)
console.log(`signature: ${signature}`)
在 Node.js (TypeScript) 中:
import { TextDecoder } from 'util';
function decode(jwt: string) {
const { 0: encodedHeader, 1: encodedPayload, 2: signature, length } = jwt.split('.');
if (length !== 3) {
throw new TypeError('Invalid JWT');
}
const decode = (input: string): JSON => { return JSON.parse(new TextDecoder().decode(new Uint8Array(Buffer.from(input, 'base64')))); };
return { header: decode(encodedHeader), payload: decode(encodedPayload), signature: signature };
}
使用 jose
by panva on GitHub,您可以使用最小的 import { decode as base64Decode } from 'jose/util/base64url'
并将 new Uint8Array(Buffer.from(input, 'base64'))
替换为 base64Decode(input)
。然后代码应该可以在浏览器和 Node.js 中运行。
这是我在研究此问题后刚刚提出的功能更丰富的解决方案:
const parseJwt = (token) => {
try {
if (!token) {
throw new Error('parseJwt# Token is required.');
}
const base64Payload = token.split('.')[1];
let payload = new Uint8Array();
try {
payload = Buffer.from(base64Payload, 'base64');
} catch (err) {
throw new Error(`parseJwt# Malformed token: ${err}`);
}
return {
decodedToken: JSON.parse(payload),
};
} catch (err) {
console.log(`Bonus logging: ${err}`);
return {
error: 'Unable to decode token.',
};
}
};
以下是一些使用示例:
const unhappy_path1 = parseJwt('sk4u7vgbis4ewku7gvtybrose4ui7gvtmalformedtoken');
console.log('unhappy_path1', unhappy_path1);
const unhappy_path2 = parseJwt('sk4u7vgbis4ewku7gvtybrose4ui7gvt.malformedtoken');
console.log('unhappy_path2', unhappy_path2);
const unhappy_path3 = parseJwt();
console.log('unhappy_path3', unhappy_path3);
const { error, decodedToken } = parseJwt('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c');
if (!decodedToken.exp) {
console.log('almost_happy_path: token has illegal claims (missing expires_at timestamp)', decodedToken);
// note: exp, iat, iss, jti, nbf, prv, sub
}
我无法在 StackOverflow 代码片段工具中使其可运行,但如果您运行该代码,您会看到以下内容:
https://i.stack.imgur.com/FdLZU.png
我让 parseJwt
函数总是返回一个对象(在某种程度上是出于静态类型的原因)。
这允许您使用以下语法:
const { decodedToken, error } = parseJwt(token);
然后,您可以在运行时测试特定类型的错误并避免任何命名冲突。
如果有人能想到对此代码进行任何低努力、高价值的更改,请随时编辑我的答案以受益于 next(person)
。
根据此处的答案和here:
const dashRE = /-/g;
const lodashRE = /_/g;
module.exports = function jwtDecode(tokenStr) {
const base64Url = tokenStr.split('.')[1];
if (base64Url === undefined) return null;
const base64 = base64Url.replace(dashRE, '+').replace(lodashRE, '/');
const jsonStr = Buffer.from(base64, 'base64').toString();
return JSON.parse(jsonStr);
};
jwt-decode.js 的 es 模块友好简化版本
function b64DecodeUnicode(str) {
return decodeURIComponent(
atob(str).replace(/(.)/g, function (m, p) {
var code = p.charCodeAt(0).toString(16).toUpperCase();
if (code.length < 2) {
code = "0" + code;
}
return "%" + code;
})
);
}
function base64_url_decode(str) {
var output = str.replace(/-/g, "+").replace(/_/g, "/");
switch (output.length % 4) {
case 0:
break;
case 2:
output += "==";
break;
case 3:
output += "=";
break;
default:
throw "Illegal base64url string!";
}
try {
return b64DecodeUnicode(output);
} catch (err) {
return atob(output);
}
}
export function jwtDecode(token, options) {
options = options || {};
var pos = options.header === true ? 0 : 1;
try {
return JSON.parse(base64_url_decode(token.split(".")[pos]));
} catch (e) {
console.log(e.message);
}
}
JSON.parse(window.atob(base64))
中删除“窗口”才能使其正常工作。在我的情况下,只有return JSON.parse(atob(base64));
然后postman.setEnvironmentVariable("userId", parseJwt(jsonData.access_token));
“access_token” 是令牌响应值的键(在您的情况下可能会有所不同)。jwt-decode
模块,因为它很小,但处理起来更好一些。Buffer.from(base64, 'base64').toString()