如何在javascript

时间:2016-07-24 12:26:08

标签: javascript jwt

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

示例令牌:xxxxxxxxx.XXXXXXXX.xxxxxxxx

结果是有效载荷:

{exp: 10012016 name: john doe, scope:['admin']}

21 个答案:

答案 0 :(得分:289)

使用unicode文本JWT解析器函数:

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

    return JSON.parse(base64);
};

答案 1 :(得分:36)

您可以使用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']}*/

答案 2 :(得分:21)

使用try - catch

的简单功能
$WC = New-Object System.Net.WebClient 
$url = 'http://ec.ccm2.net/www.commentcamarche.net/download/files/SFDLC_v2.0_bin.zip'
$Filename = ($url.Split('/') | Select -Last 1)     

$wc.DownloadFile($url,"C:\__TMP\$Filename")

谢谢!

答案 3 :(得分:13)

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

答案 4 :(得分:7)

@Peheje会工作,但你会遇到unicode问题。 为了解决这个问题,我使用了https://stackoverflow.com/a/30106551/5277071;

上的代码

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();
})
textarea{width:300px; height:60px; display:block}
<form id="form" action="parse">
  <textarea name="jwt">eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkrDtGhuIETDs8OoIiwiYWRtaW4iOnRydWV9.469tBeJmYLERjlKi9u6gylb-2NsjHLC_6kZNdtoOGsA</textarea>
  <textarea name="out"></textarea>
  <input type="submit" value="parse" />
</form>

答案 5 :(得分:4)

我使用此函数根据this回答获取有效负载,标题,exp(到期时间),iat(发布时间)

public static Matcher<View> withUnderlinedText() {
    return new BoundedMatcher<View, TextView>(TextView.class) {
        @Override
        protected boolean matchesSafely(TextView textView) {
                CharSequence charSequence = textView.getText();
                UnderlineSpan[] underlineSpans = ((SpannedString) charSequence).getSpans(0, charSequence.length(), UnderlineSpan.class);

                return underlineSpans != null && underlineSpans.length > 0;    
        }

        @Override
        public void describeTo(Description description) {
        }
    };
}

答案 6 :(得分:2)

Guy和Peheje已经回答了这个问题。对于像我这样的初学者来说,在示例中定义导入行也很有帮助。

我花了几分钟才发现令牌是回发的全套证书(整个JWT令牌,而不仅仅是idToken部分)。一旦你知道它就直截了当。

import jwt_decode from 'jwt-decode';

var token = 'eyJ0eXAiO.../// jwt token';
var decoded = jwt_decode(token);

/*{exp: 10012016 name: john doe, scope:['admin']}*/

答案 7 :(得分:2)

我在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长度无效的问题 所以,我需要一种更稳定的方式。

我希望它会对你有所帮助。

答案 8 :(得分:2)

由于Node.js环境中不存在“窗口”对象, 我们可以使用以下代码行:

let base64Url = token.split('.')[1]; // token you get
let base64 = base64Url.replace('-', '+').replace('_', '/');
let decodedData = JSON.parse(Buffer.from(base64, 'base64').toString('binary'));

它非常适合我。希望对您有所帮助。

答案 9 :(得分:2)

这是我研究了这个问题后才提出的功能更丰富的解决方案:

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代码段工具中使该代码可运行,但是如果您运行该代码,则大约可以看到以下内容:

enter image description here

我使parseJwt函数始终返回一个对象(出于某种原因,出于静态键入的原因)。

这使您可以利用以下语法:

const { decodedToken, error } = parseJwt(token);

然后,您可以在运行时测试特定类型的错误,并避免任何命名冲突。

如果任何人都可以想到此代码的任何努力,高价值的更改,请随时编辑我的答案以获取next(person)的好处。

答案 10 :(得分:1)

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

此版本特别好,不仅因为它不依赖于任何npm模块,而且还因为它不依赖于任何node.js内置模块(如Buffer),因此这里还有其他解决方案。在浏览器中使用和当然会失败(除非进行多填充,但首先没有理由这样做)。

/**
 * Returns a JS object representation of a Javascript Web Token from it's common encoded
 * string form.
 *
 * @export
 * @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 (e) {
    return undefined
  }
}

为完成起见,这也是原始的javascript版本:

/**
 * Returns a JS object representation of a Javascript Web Token from it's common encoded
 * string form.
 *
 * @export
 * @template T the expected shape of the parsed token
 * @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 (e) {
    return undefined
  }
}

答案 11 :(得分:1)

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

atob(token.split('.')[1]);

或直接将其解析为json对象:

JSON.parse(atob(token.split('.')[1]));

了解atob()btoa()内置的javascript函数Base64 encoding and decoding - Web APIs | MDN

答案 12 :(得分:0)

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

let payload = JSON.parse(Buffer.from(token.split(".")[1], "base64url"));

答案 13 :(得分:0)

一个 es-module 友好的简化版 jwt-decode.js

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);
  }
}

答案 14 :(得分:0)

在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中使用。

答案 15 :(得分:0)

如果您使用Node.JS, 您可以通过以下方式使用本机Buffer模块:

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

你很好::)

答案 16 :(得分:0)

基于GitHub - auth0/jwt-decode的答案。更改了输入/输出,以包括字符串拆分和返回对象{标头,有效负载,签名},因此您只需传递整个令牌即可。

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

    };

答案 17 :(得分:0)

用于解码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}`)

答案 18 :(得分:-1)

运行Javascript node.js表示我必须首先按如下所示安装软件包:

npm install jwt-decode --save

然后在我的app.js代码中获取软件包:

const jwt_decode = require('jwt-decode');

然后运行代码:

let jwt_decoded = jwt_decode(jwt_source);

然后魔术:

console.log('sub:',jwt_decoded.sub);

答案 19 :(得分:-1)

根据此处的答案和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);
};

答案 20 :(得分:-1)

jwt.io的所有功能都不支持所有语言。在NodeJ中,您可以使用

var decoded = jwt.decode(token);