2015-04-20 11 views
8

Provo a creare JSON Web Token in Java con jjwt libraryCome estendere il token web java json time di scadenza?

Ma ho problemi quando tento di estendere il tempo di scadenza.

Provo con il codice qui sotto.

public class Main { 
public static void main(String args[]) { 
    byte[] key = new byte[64]; 
    new SecureRandom().nextBytes(key); 
    Date date = new Date(); 
    long t = date.getTime(); 
    Date expirationTime = new Date(t + 5000l); // set 5 seconds 

    String compact = Jwts.builder().setSubject("Joe").setExpiration(expirationTime).signWith(SignatureAlgorithm.HS256, key).compact(); 
    System.out.println("compact : " + compact); 
    try { 
     String unpack = Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().getSubject(); 
     System.out.println("unpackage 0 : " + unpack); 

     // check if the expiration work. 
     Thread.sleep(3000); 
     System.out.println("unpackage 1 : " + Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().getSubject()); 

     //extend the expration time. 
     Date date1 = new Date(); 
     long t1 = date1.getTime(); 
     Date expirationTime1 = new Date(t1 + 5000l); //prolongation 5 seconds 
     Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().setExpiration(expirationTime1).getSubject(); 

     // check if the extend expiration work. 
     Thread.sleep(3000);    
     System.out.println("unpackage 2 : " + Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().getSubject()); 
    } catch (InterruptedException | ExpiredJwtException ex) { 
     System.out.println("exception : " + ex.getMessage()); 
     Thread.currentThread().interrupt(); 
    } 
} 

Il risultato è:

 
compact : eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UiLCJleHAiOjE0Mjk2NjU1MjB9.oMY2mDHvNoMZqBfic41LbiKvAyi93wIfu_WgIADb9Wc 
unpackage 0 : Joe 
unpackage 1 : Joe 
exception : JWT expired at 2015-04-22T08:18:40+0700. Current time: 2015-04-22T08:18:42+0700 

Così dire, la corsa non posso unpackage2, Perché era di scadenza.

Sto cercando di estendere il tempo di scadenza.

Perché applico il codice sull'applicazione Web.

Se l'utente continua a connettersi con la mia applicazione, non dovrebbe ottenere il timeout del token.

Ho trovato another question come il mio.

+0

Ho copiato e incollato il codice in un test di unità e l'ho eseguito contro JJWT 0.3 e 0.4 e non posso riprodurre il problema che stai incontrando. Potresti incollare l'output del tuo codice quando lo esegui? –

risposta

9

Il problema è con il codice di analisi:

Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().setExpiration(expirationTime1).getSubject(); 

In questa linea, si sta modificando la JWT che viene restituito dal parser. In altre parole, quanto sopra è equivalente a questo:

Jws<Claims> jws = Jwts.parser().setSigningKey(key).parseClaimsJws(compact); 
jws.getBody().setExpiration(expirationTime1).getSubject(); 

Notate come questo codice modifica il JWT restituito dal parser? Non - e non può - modificare il JWT rappresentato dalla stringa originale compact.

tua prossima riga di codice dopo che tenta di analizzare la stringa originale (non modificato) compact:

// check if the extend expiration work. 
Thread.sleep(3000);    
System.out.println("unpackage 2 : " + Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().getSubject()); 

Ma sappiamo che questo non funzionerà perché modificare lo stato della JWT restituito dal parser fa non ha alcun effetto sulla stringa originale compact.

Se l'utente presenta una JWT per l'applicazione web e si desidera 'estendere la vita' del token in modo che non scade, è necessario generare una nuova JWT e inviare tale JWT indietro per l'utente . L'utente deve inviare il nuovo JWT alle richieste future. Continui a ripetere questo processo per tutto il tempo che vuoi consentire all'utente di continuare a parlare con la tua applicazione web senza dover effettuare nuovamente l'accesso.

Vorrei precisare che se non vuoi preoccuparti di nessuna di queste cose, Stormpath puoi eseguire l'autenticazione del token utente e JWT tra il browser e l'app automaticamente per te - non devi costruire nessuno dei questo te stesso (rivelazione: I'm Stormpath's CTO).

Infine, potreste essere interessati a sapere che la suite di test di JJWT convalida già il comportamento corretto in numerosi luoghi per entrambi i casi di utilizzo di token scaduti e prematuri:

Ma, non devi credermi sulla parola :) Ecco il tuo codice, modificato in modo che il tuo exp modifiche Iration funzionano come descritto:

public class Main { 

public static void main(String args[]) { 
    byte[] key = new byte[64]; 
    new SecureRandom().nextBytes(key); 
    Date date = new Date(); 
    long t = date.getTime(); 
    Date expirationTime = new Date(t + 5000l); // set 5 seconds 

    String compact = Jwts.builder().setSubject("Joe").setExpiration(expirationTime).signWith(SignatureAlgorithm.HS256, key).compact(); 
    System.out.println("compact : " + compact); 
    try { 
     String unpack = Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().getSubject(); 
     System.out.println("unpackage 0 : " + unpack); 

     // check if the expiration work. 
     Thread.sleep(3000); 
     System.out.println("unpackage 1 : " + Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().getSubject()); 

     //Create a *new* token that reflects a longer extended expiration time. 
     Date date1 = new Date(); 
     long t1 = date1.getTime(); 
     Date expirationTime1 = new Date(t1 + 5000l); //prolongation 5 seconds 

     String compact2 = Jwts.builder().setSubject("Joe").setExpiration(expirationTime1).signWith(SignatureAlgorithm.HS256, key).compact(); 

     // check if the extend expiration work. 
     Thread.sleep(3000); 
     System.out.println("unpackage 2 : " + Jwts.parser().setSigningKey(key).parseClaimsJws(compact2).getBody().getSubject()); 

     Thread.sleep(1000); 
    } catch (InterruptedException | ExpiredJwtException ex) { 
     System.out.println("exception : " + ex.getMessage()); 
     Thread.currentThread().interrupt(); 
    } 
} 
} 

Si noti che un 2 ° nuova JWT (compact2) aveva bisogno di essere generato per riflettere il nuovo/ultima ora di scadenza. Non è possibile modificare un JWT analizzato e aspettarsi che le modifiche si applichino al valore originale compatto.

In sintesi, utilizzare Jwts.parser() quando è necessario analizzare una stringa JWT per ottenere una rappresentazione dell'oggetto Java del JWT. Utilizzare Jwts.builder() quando è necessario creare o modificare un JWT per produrre una nuova rappresentazione String compatta.

Spero che questo aiuti!

+0

Ok, c'è un modo per generare un nuovo token con solo il gettone scaduto nelle tue mani? Quindi quello che voglio fare è analizzare il token scaduto, ottenere oggetto dal suo corpo (so che è scaduto, MA è valido in termini di controllo del corpo e dell'intestazione con una chiave di firma), quindi voglio usare questo soggetto estratto per generare il valido token auth. Grazie – hsestupin

+0

Ok! Capito! Esiste un metodo 'io.jsonwebtoken.ClaimJwtException # getClaims' – hsestupin

+0

@hsestupin no, dovresti * mai * fidarti dei token scaduti o di quelli che non superano la convalida della firma. *Mai*. Se lo fai, sei in palese violazione delle specifiche JWT ed è una bandiera gialla che devi ripensare al tuo design (che stai cercando di fare qualcosa che dovrebbe essere fatto in un modo diverso). –

Problemi correlati