如何在javascript中解码jwt令牌

Chr*_*8er 167 javascript jwt

如何使用JavaScript解码JWT的有效负载?没有图书馆.因此令牌只返回我的前端应用程序可以使用的有效负载对象.

示例令牌: xxxxxxxxx.XXXXXXXX.xxxxxxxx

结果就是有效载荷:

{exp: 10012016 name: john doe, scope:['admin']}
Run Code Online (Sandbox Code Playgroud)

Peh*_*eje 362

这会有用吗?

function parseJwt (token) {
    var base64Url = token.split('.')[1];
    var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
    var jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));

    return JSON.parse(jsonPayload);
};
Run Code Online (Sandbox Code Playgroud)

正如Racing Tadpole的评论中提到的,javascript replace仅替换第一次出现,而是使用正则表达式:

function parseJwt (token) {
    var base64Url = token.split('.')[1];
    var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
    var jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));

    return JSON.parse(jsonPayload);
};
Run Code Online (Sandbox Code Playgroud)

  • 上面的解决方案只替换令牌中的第一个" - "和"_"(一个让我痛苦的javascript"功能").只需将答案中的第三行替换为:`var base64 = base64Url.replace(/ - /g,'+').replace(/ _/g,'/');` (11认同)
  • 最好使用 `jwt-decode` 模块,因为它很小但处理得更好一些。 (4认同)
  • `为什么需要将“-”替换为“+”,将“_”替换为“/”?`因为您需要将 [base64url](https://base64.guru/standards/base64url) 编码转换为通常的编码首先是base64。 (3认同)
  • 不幸的是,这似乎不适用于unicode文本。 (2认同)
  • 该解决方案甚至可以在Postman中使用(测试水龙头),因为它不需要安装任何附加库。我用它从auth令牌中提取userid。 (2认同)
  • 注意:在Postman中,我不得不从`JSON.parse(window.atob(base64))`删除"窗口"以使其工作.只是`返回JSON.parse(atob(base64));`然后`postman.setEnvironmentVariable("userId",parseJwt(jsonData.access_token));`"access_token"在我的例子中是令牌的响应值的关键(可能)在你的情况不同). (2认同)
  • 也许对某些人来说微不足道,但不要忘记通过添加 const atob = require('atob'); 将 atob 添加为依赖项; (2认同)
  • 如果您使用 NodeJS,并且无法访问 atob,请改用:`Buffer.from(base64, 'base64').toString()` (2认同)
  • 在前端解析令牌是个好主意吗? (2认同)

Guy*_*Guy 43

你可以使用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']}*/
Run Code Online (Sandbox Code Playgroud)

  • "我的意思是没有图书馆." (39认同)
  • 他们是这个库的问题。主要使用firefox。我遇到的问题是,如果注销或过期导致 token == null ;这只会因错误而终止页面。 (3认同)

Raj*_*jan 34

简单的功能与try - catch

const parseJwt = (token) => {
  try {
    return JSON.parse(atob(token.split('.')[1]));
  } catch (e) {
    return null;
  }
};
Run Code Online (Sandbox Code Playgroud)

谢谢!

  • [JWT 使用 base64url](https://tools.ietf.org/html/rfc7519#section-3) ([RFC 4648 §5](https://tools.ietf.org/html/rfc4648#section-5) )。这个答案使用base64。这个答案是错误的。 (26认同)
  • `atob` 已知 [unicode 问题](https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem) (3认同)

Muh*_*ssa 33

您可以使用纯 javascriptatob()函数将令牌解码为字符串:

atob(token.split('.')[1]);
Run Code Online (Sandbox Code Playgroud)

或者直接解析成json对象:

JSON.parse(atob(token.split('.')[1]));
Run Code Online (Sandbox Code Playgroud)

阅读atob()btoa()内置javascript 函数Base64 编码和解码- Web APIs | MDN

  • [JWT 使用 base64url](https://tools.ietf.org/html/rfc7519#section-3) ([RFC 4648 §5](https://tools.ietf.org/html/rfc4648#section-5) )。这个答案使用base64。这个答案是错误的。 (3认同)

has*_*e72 17

function parseJwt(token) {
  var base64Payload = token.split('.')[1];
  var payload = Buffer.from(base64Payload, 'base64');
  return JSON.parse(payload.toString());
}
Run Code Online (Sandbox Code Playgroud)
let payload= parseJwt("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c");
console.log("payload:- ", payload);
Run Code Online (Sandbox Code Playgroud)

如果使用节点,您可能必须使用缓冲包:

npm install buffer
var Buffer = require('buffer/').Buffer
Run Code Online (Sandbox Code Playgroud)

  • 我使用它而不是“atob”,因为它已被弃用。 (4认同)
  • 这是 Node.js 的一个很好的答案。但在浏览器中,“Buffer”不存在(您的框架可能会添加一个大的polyfill),而“atob”仅在 Node.js 上被弃用,并且在浏览器中使用完全没问题。 (4认同)

Avi*_*vik 11

由于 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'));
Run Code Online (Sandbox Code Playgroud)

它非常适合我。希望能帮助到你。


Vas*_*iak 10

如果使用node.js 16或更高版本,您可以使用内置的base64url编码器/解码器。

let payload = JSON.parse(Buffer.from(token.split(".")[1], "base64url"));
Run Code Online (Sandbox Code Playgroud)


Sof*_*ixt 8

我使用此函数根据答案获取有效负载、标头、exp(到期时间)、iat(发布于)

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)
}
Run Code Online (Sandbox Code Playgroud)


小智 7

@Peheje会工作,但你会遇到unicode问题.要修复它,我使用/sf/answers/2107458601/上的代码;

let b64DecodeUnicode = str =>
  decodeURIComponent(
    Array.prototype.map.call(atob(str), c =>
      '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
    ).join(''))

let parseJwt = token =>
  JSON.parse(
    b64DecodeUnicode(
      token.split('.')[1].replace('-', '+').replace('_', '/')
    )
  )


let form = document.getElementById("form")
form.addEventListener("submit", (e) => {
   form.out.value = JSON.stringify(
      parseJwt(form.jwt.value)
   )
   e.preventDefault();
})
Run Code Online (Sandbox Code Playgroud)
textarea{width:300px; height:60px; display:block}
Run Code Online (Sandbox Code Playgroud)
<form id="form" action="parse">
  <textarea name="jwt">eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkrDtGhuIETDs8OoIiwiYWRtaW4iOnRydWV9.469tBeJmYLERjlKi9u6gylb-2NsjHLC_6kZNdtoOGsA</textarea>
  <textarea name="out"></textarea>
  <input type="submit" value="parse" />
</form>
Run Code Online (Sandbox Code Playgroud)


Cha*_*m.E 6

如果您使用 Node.JS,您可以通过执行以下操作来使用本机 Buffer 模块:

const token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImp0aSI6ImU3YjQ0Mjc4LTZlZDYtNDJlZC05MTZmLWFjZDQzNzhkM2U0YSIsImlhdCI6MTU5NTg3NzUxOCwiZXhwIjoxNTk1ODgxMTE4fQ.WXyDlDMMSJAjOFF9oAU9JrRHg2wio-WolWAkAaY3kg4';
const tokenDecodablePart = token.split('.')[1];
const decoded = Buffer.from(base64Url, 'base64').toString();
console.log(decoded)
Run Code Online (Sandbox Code Playgroud)

你很高兴去:-)


man*_*nak 6

如果您使用的是Typescript vanilla JavaScript,这是一个零依赖项,可以在您的项目简单函数中复制粘贴(基于 @Rajan Maharjan 的答案)。

这个答案特别好,不仅因为它不依赖于任何 npm 模块,还因为它不依赖于Buffer这里的其他一些解决方案正在使用的任何 node.js 内置模块(如),当然会失败浏览器(除非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
  }
}
Run Code Online (Sandbox Code Playgroud)

为了完成,这里也是香草 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
  }
}
Run Code Online (Sandbox Code Playgroud)

  • @LorenzLeutgeb 我希望在 NPM 上发布的旨在解决 JWT 解码/解析问题的库的 github 问题中看到所有有效的评论。考虑到这个 Stack Overflow 问题上的人很可能正在寻找复制意大利面**脚本**而不是库,我尽力平衡改进我在这里看到的所有其他答案,同时保持代码的可读性和可扩展/可维护。干杯并感谢您花时间澄清这些事情。 (2认同)

小智 5

我在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;
  }
}
Run Code Online (Sandbox Code Playgroud)

在某些情况下(某些开发平台),
最佳答案(目前)面临 base64 长度无效的问题。
所以,我需要一种更稳定的方式。

我希望它会帮助你。


cal*_*san 5

基于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])
        };

    };
Run Code Online (Sandbox Code Playgroud)


dro*_*rdk 5

您可以定义并使用这个衬垫函数:

jwtDecode = b => JSON.parse(Buffer.from(b.split('.')[1], 'base64').toString('binary'));
Run Code Online (Sandbox Code Playgroud)