Bir kitaplık kullanmadan javascript jwt jetonunu çözmek için?


209

JavaScript kullanarak JWT'nin yükünü nasıl çözebilirim? Kütüphane olmadan. Jeton sadece ön uç uygulamam tarafından tüketilebilen bir yük nesnesi döndürüyor.

Örnek simge: xxxxxxxxx.XXXXXXXX.xxxxxxxx

Ve sonuç yüktür:

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

1
Nasıl kodlandı? Sadece tersini yap. Paylaşılan sırra ihtiyacınız olacak.
Şanslı Soni

Php kütüphanesini kullanan arka uç api tarafından kodlanmıştır. Burada ihtiyacım sanırım base64 kullanarak kodlanmış yük ...
Chrisk8er

1
Jwt.io web sitesine gitmeyi ve sağladığı JavaScript kitaplığını almayı deneyebilirsiniz .
Quentin

12
Bu soru biraz trafik içerdiğinden, bir feragatname eklemek istiyorum: İmzayı onaylamadan, jetonun yükünü körü körüne çözerseniz, güvenlik sorunlarıyla karşılaşabilirsiniz (veya olmayabilir)! Bu yığın akışı sorusunda sağlanan herhangi bir kodu körü körüne kullanmadan önce güvenlik mimarinizi anladığınızdan emin olun.
Carsten Hoffmann

4
@CarstenHoffmann Ve imzayı tam olarak nasıl doğrularım?
Saurabh Tiwari

Yanıtlar:


468

Unicode metin JWT ayrıştırıcı işlevi çalışma:

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

2
Ne yazık ki bu unicode metinle çalışmıyor gibi görünüyor.
Paul McMahon

2
Bu çözüm Postacı'da bile kullanılabilir (sınamalar) herhangi bir ek kütüphane kurulumu gerektirmediğinden. Auth token'den userid ayıklamak için kullandım.
wlad

2
NOT: Postacı JSON.parse(window.atob(base64))çalışmasını sağlamak için "pencere" kaldırmak zorunda kaldı . Sadece return JSON.parse(atob(base64));ve sonra postman.setEnvironmentVariable("userId", parseJwt(jsonData.access_token)); "access_token" benim durumumda jetonun değerinin anahtarıdır (sizin durumunuzda farklılık gösterebilir).
wlad

12
Yukarıdaki çözüm, yalnızca jetondaki ilk "-" ve "_" yerine geçer (bana acı çekmeye devam eden bir javascript "özelliği"). Cevabın üçüncü satırını şununla değiştirin:var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
Yarış Tadpole

2
jwt-decodeModülü kullanmak daha iyidir, çünkü küçük ama biraz daha iyi işlem yapar.
Rantiev


47

Jwt-decode kullanabilirsiniz , böylece yazabilirsiniz:

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']}*/

67
"Yani kütüphane yok."
SherloxTV

Bu kütüphane ile ilgili problemler. Temelde firefox kullanımda. Karşılaştığım sorun, oturumu kapatma veya süresi dolan bir belirteç == null olursa; bunun sadece sayfayı bir hata ile öldürdüğünü.
LUser

1
@ApertureSecurity bu hatayı yakalamak gerekir, ama kuşkusuz bu yüzden bu kütüphane kullanmak istemiyorum
Luke Robertson

Bu GZIP'i desteklemiyor gibi görünüyor. Aslında, iddialar için GZIP'i destekleyen herhangi bir JS kütüphanesi bulamıyorum.
Andrew T Finnell


9

@Peheje çalışacak, ancak unicode ile sorun yaşayacaksınız. Düzeltmek için https://stackoverflow.com/a/30106551/5277071 adresindeki kodu kullanıyorum ;

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>


+1 ancak Racing Tadpole'un Peheje'nin cevabı hakkındaki yorumu doğruysa (değiştirme çağrıları sadece ilk örneğin yerini alacaktır), aynı düzeltme burada geçerlidir.
Gary McGill

9

"Window" nesnesi nodejs ortamında bulunmadığından, aşağıdaki kod satırlarını kullanabiliriz:

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

Benim için mükemmel çalışıyor. Umarım yardımcı olur.


1
düğüm js için mükemmel cevap
ireshan pathirana

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

Düğüm kullanıyorsanız, arabellek paketini kullanmanız gerekebilir:

npm install buffer
var Buffer = require('buffer/').Buffer

6

Bu cevaba dayanarak yük, başlık, exp (Sona Erme Süresi), iat (Çıkış Tarihi) almak için bu işlevi kullanıyorum

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

Bu cevap biraz daha iyi, ama iki buçuk sorunu var. İlk olarak, imzayı kontrol etmez (dizi öğesi 2). İkincisi, REPLACE'ler düzgün çalışmaz, çünkü normal ifadedeki "g" bayrağını kaçırırlar (Racing Tadpole'ın başka bir yayına yorumladığı gibi JWT'deki yalnızca - ve _'in ilk tekrarlarının yerini alacaklar). Ve yarısı: 0 ve 1 dizi öğelerinin kodunu çözmek için, tüm kodu çoğaltmak yerine bir FOR döngüsü kullanmış olabilirsiniz (kısa bir koddur, ancak daha verimli hale getirilebilir, çünkü SPLIT iki kez yürütülür ).
Cyberknight

4

jwt.io'nun tüm özellikleri tüm dilleri desteklemez. NodeJ'lerde şunları kullanabilirsiniz:

var decoded = jwt.decode(token);

1
Kütüphane olmadan, token {var payload = token.split ('.') [1]) 'nin ikinci bölümünde base64 kod çözme işlemini gerçekleştirirsiniz; } Ardından base64 kod çözme işlemini gerçekleştirin {var decodedData = atob (faydalı yük); }
Jithin Vijayan

4

Ben jwt.io bu kodu bulundu ve iyi çalışıyor.

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

Bazı durumlarda (belirli geliştirme platformları),
en iyi yanıt (şimdilik) geçersiz base64 uzunluğu sorunuyla karşı karşıyadır.
Bu yüzden daha istikrarlı bir yola ihtiyacım vardı.

Umarım size yardımcı olur.


2

Hem Guy hem de Peheje soruyu zaten yanıtladı. Benim gibi toplam yeni başlayanlar için, örnekte içe aktarma satırına sahip olmak da yardımcı oldu.

Ayrıca, jetonun geri gönderilen kimlik bilgilerinin tamamı olduğunu anlamak birkaç dakika sürdü (sadece idToken kısmı değil, tüm JWT jetonu). Bir kez bildiğinizde ..

import jwt_decode from 'jwt-decode';

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

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


2
OP'nin talep ettiği şeye karşı da başka bir kullanıcıyla aynı cevabı
yayınlamak

2

JSON Web Simgesini (JWT) Kod Çözmek için Basit NodeJS Çözümü

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

2

Cevap GitHub - auth0 / jwt-decode tabanlı . Girdi / çıktıyı dize bölme ve dönüş nesnesi {header, loadload, signature} içerecek şekilde değiştirdi, böylece jetonun tamamını geçirebilirsiniz.

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

    };

1

İşte bu soruyu inceledikten sonra yaptığım daha zengin özellikli bir çözüm:

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.',
        };
    }
};

İşte bazı kullanım örnekleri:

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 kod snippet aracında bu runnable yapamadım, ama işte bu kodu çalıştırdıysanız ne göreceksiniz:

resim açıklamasını buraya girin

Ben parseJwtfonksiyonu her zaman bir nesne döndürdüm (statik yazım nedenleriyle bir dereceye kadar).

Bu, aşağıdaki gibi bir sözdizimi kullanmanızı sağlar:

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

Daha sonra çalışma zamanında belirli hata türlerini test edebilir ve herhangi bir adlandırma çarpışmasını önleyebilirsiniz.

Herkes bu çaba az çaba, yüksek değer değişiklikleri düşünebilirsiniz, yararına cevabımı düzenlemek için çekinmeyin next(person).


0

Burada ve burada verilen cevaplara dayanarak :

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

-1

Javascript node.js express'i çalıştırarak önce paketi aşağıdaki gibi yüklemem gerekti:

npm install jwt-decode --save

sonra benim app.js kodu paketi almak:

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

Sonra kodu çalıştırın:

let jwt_decoded = jwt_decode(jwt_source);

Sonra sihir:

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

4
"kütüphane kullanmadan" hatırlayın
Olaf

1
Tamam yeterince adil. Ancak aynı sorunla karşı karşıya kaldım ve kütüphane kullanamama gibi bir kısıtlamam yoktu. Bu benim için çalıştı. Başkasının benzer bir sorunla karşı karşıya olduğu ve aynı kısıtlamaya sahip olmadığı için yayınlandım.
David White
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.