web-dev-qa-db-fra.com

Bibliothèque JWT (JSON Web Token) pour Java

Je travaille sur une application Web développée à l'aide de Java et d'AngularJS et j'ai choisi d'implémenter l'authentification et l'autorisation par jeton. Pour les besoins de l'exercice, je suis parvenu au point d'envoyer les informations d'identification au serveur, de générer un magasin de jetons aléatoire et de les renvoyer au client. À chaque demande adressée au serveur, j'attache le jeton dans l'en-tête et cela fonctionne parfaitement. Pour l'authentification, le point de vue est parfait et n'aurait pas besoin de plus.

Cependant, je souhaite maintenant garder une trace du type d'utilisateur (admin, utilisateur régulier ...), ainsi que de son identifiant ou de tout autre champ unique; si j'ai bien compris, je dois chiffrer le jeton que je renvoie au client lors de l'action de connexion. Est-ce exact?

Avez-vous utilisé une bibliothèque JWT et pouvez-vous générer, chiffrer et déchiffrer de tels jetons? Un lien vers l'API de la bibliothèque et la dépendance à Maven serait très apprécié.

Merci

66

Si quelqu'un a besoin d'une réponse,

J'ai utilisé cette bibliothèque: http://connect2id.com/products/nimbus-jose-jwt Maven ici: http://mvnrepository.com/artifact/com.nimbusds/nimbus- jose-jwt/2.10.1

22

JJWT vise à être le plus facile à utiliser et à comprendre la bibliothèque JWT pour la machine virtuelle Java et Android:

https://github.com/jwtk/jjwt

49
Les Hazlewood

Cette bibliothèque semble bien fonctionner: https://code.google.com/p/jsontoken/ .

Cela dépend de Google Guava. Voici les artefacts Maven:

<dependency>
    <groupId>com.googlecode.jsontoken</groupId>
    <artifactId>jsontoken</artifactId>
    <version>1.0</version>
</dependency>
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>18.0</version>
</dependency>

La bibliothèque est en fait utilisée par Google Wallet.

Voici comment créer un fichier JWT, le vérifier et le désérialiser:

import Java.security.InvalidKeyException;
import Java.security.SignatureException;
import Java.util.Calendar;
import Java.util.List;

import net.oauth.jsontoken.JsonToken;
import net.oauth.jsontoken.JsonTokenParser;
import net.oauth.jsontoken.crypto.HmacSHA256Signer;
import net.oauth.jsontoken.crypto.HmacSHA256Verifier;
import net.oauth.jsontoken.crypto.SignatureAlgorithm;
import net.oauth.jsontoken.crypto.Verifier;
import net.oauth.jsontoken.discovery.VerifierProvider;
import net.oauth.jsontoken.discovery.VerifierProviders;

import org.Apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.joda.time.DateTime;

import com.google.common.collect.Lists;
import com.google.gson.JsonObject;


/**
 * Provides static methods for creating and verifying access tokens and such. 
 * @author davidm
 *
 */
public class AuthHelper {

    private static final String AUDIENCE = "NotReallyImportant";

    private static final String ISSUER = "YourCompanyOrAppNameHere";

    private static final String SIGNING_KEY = "LongAndHardToGuessValueWithSpecialCharacters@^($%*$%";

    /**
     * Creates a json web token which is a digitally signed token that contains a payload (e.g. userId to identify 
     * the user). The signing key is secret. That ensures that the token is authentic and has not been modified.
     * Using a jwt eliminates the need to store authentication session information in a database.
     * @param userId
     * @param durationDays
     * @return
     */
    public static String createJsonWebToken(String userId, Long durationDays)    {
        //Current time and signing algorithm
        Calendar cal = Calendar.getInstance();
        HmacSHA256Signer signer;
        try {
            signer = new HmacSHA256Signer(ISSUER, null, SIGNING_KEY.getBytes());
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        }

        //Configure JSON token
        JsonToken token = new net.oauth.jsontoken.JsonToken(signer);
        token.setAudience(AUDIENCE);
        token.setIssuedAt(new org.joda.time.Instant(cal.getTimeInMillis()));
        token.setExpiration(new org.joda.time.Instant(cal.getTimeInMillis() + 1000L * 60L * 60L * 24L * durationDays));

        //Configure request object, which provides information of the item
        JsonObject request = new JsonObject();
        request.addProperty("userId", userId);

        JsonObject payload = token.getPayloadAsJsonObject();
        payload.add("info", request);

        try {
            return token.serializeAndSign();
        } catch (SignatureException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Verifies a json web token's validity and extracts the user id and other information from it. 
     * @param token
     * @return
     * @throws SignatureException
     * @throws InvalidKeyException
     */
    public static TokenInfo verifyToken(String token)  
    {
        try {
            final Verifier hmacVerifier = new HmacSHA256Verifier(SIGNING_KEY.getBytes());

            VerifierProvider hmacLocator = new VerifierProvider() {

                @Override
                public List<Verifier> findVerifier(String id, String key){
                    return Lists.newArrayList(hmacVerifier);
                }
            };
            VerifierProviders locators = new VerifierProviders();
            locators.setVerifierProvider(SignatureAlgorithm.HS256, hmacLocator);
            net.oauth.jsontoken.Checker checker = new net.oauth.jsontoken.Checker(){

                @Override
                public void check(JsonObject payload) throws SignatureException {
                    // don't throw - allow anything
                }

            };
            //Ignore Audience does not mean that the Signature is ignored
            JsonTokenParser parser = new JsonTokenParser(locators,
                    checker);
            JsonToken jt;
            try {
                jt = parser.verifyAndDeserialize(token);
            } catch (SignatureException e) {
                throw new RuntimeException(e);
            }
            JsonObject payload = jt.getPayloadAsJsonObject();
            TokenInfo t = new TokenInfo();
            String issuer = payload.getAsJsonPrimitive("iss").getAsString();
            String userIdString =  payload.getAsJsonObject("info").getAsJsonPrimitive("userId").getAsString();
            if (issuer.equals(ISSUER) && !StringUtils.isBlank(userIdString))
            {
                t.setUserId(new ObjectId(userIdString));
                t.setIssued(new DateTime(payload.getAsJsonPrimitive("iat").getAsLong()));
                t.setExpires(new DateTime(payload.getAsJsonPrimitive("exp").getAsLong()));
                return t;
            }
            else
            {
                return null;
            }
        } catch (InvalidKeyException e1) {
            throw new RuntimeException(e1);
        }
    }


}

public class TokenInfo {
    private ObjectId userId;
    private DateTime issued;
    private DateTime expires;
    public ObjectId getUserId() {
        return userId;
    }
    public void setUserId(ObjectId userId) {
        this.userId = userId;
    }
    public DateTime getIssued() {
        return issued;
    }
    public void setIssued(DateTime issued) {
        this.issued = issued;
    }
    public DateTime getExpires() {
        return expires;
    }
    public void setExpires(DateTime expires) {
        this.expires = expires;
    }
}

Ceci est basé sur le code ici: https://developers.google.com/wallet/instant-buy/about-jwts Et ici: https://code.google.com/ p/wallet-online-sample-Java/source/naviguer/src/com/google/portefeuille/en ligne/jwt/util/WalletOnlineService.java? r = 08b3333bd7260b20846d7d96d3cf15be8a128dfa

13
Marquez

En vous référant à https://jwt.io/ , vous pouvez trouver les implémentations de jwt dans de nombreuses langues, dont Java. Le site fournit également des comparaisons entre ces implémentations (les algorithmes qu’elles supportent et ....).

Pour Java ces bibliothèques sont mentionnées:

12
Alireza Fattahi

L’IETF a suggéré Jose Libs sur son wiki: http://trac.tools.ietf.org/wg/jose/trac/wiki

Je recommande fortement de les utiliser pour la signature. Je ne suis pas un gars Java, mais jose4j semble être une bonne option. A de beaux exemples aussi: https://bitbucket.org/b_c/jose4j/wiki/JWS%20Examples

Mise à jour: jwt.io fournit une comparaison soignée de plusieurs bibliothèques liées à jwt et de leurs fonctionnalités. Un doit vérifier!

J'adorerais entendre parler de ce que les autres développeurs Java préfèrent.

7
Priyeshj

J'ai trouvé cela petit et complet https://github.com/auth0/Java-jwt

5
mfirry

Cette page conserve les références aux implémentations dans divers langages, y compris Java, et compare les fonctionnalités: http://kjur.github.io/jsjws/index_mat.html

3
Hans Z.

Si vous avez seulement besoin d'analyser des jetons non signés non signés, vous pouvez utiliser ce code:

boolean parseJWT_2() {
    String authToken = getToken();
    String[] segments = authToken.split("\\.");
    String base64String = segments[1];
    int requiredLength = (int)(4 * Math.ceil(base64String.length() / 4.0));
    int nbrPaddings = requiredLength - base64String.length();

    if (nbrPaddings > 0) {
        base64String = base64String + "====".substring(0, nbrPaddings);
    }

    base64String = base64String.replace("-", "+");
    base64String = base64String.replace("_", "/");

    try {
        byte[] data = Base64.decode(base64String, Base64.DEFAULT);

        String text;
        text = new String(data, "UTF-8");
        tokenInfo = new Gson().fromJson(text, TokenInfo.class);
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }

    return true;
}
2
Anton Duzenko

https://github.com/networknt/jsontoken

Ceci est une fourchette de google original jsontoken

Il n'a pas été mis à jour depuis le 11 septembre 2012 et dépend d'anciens paquets.

Ce que j'ai fait:

Convert from Joda time to Java 8 time. So it requires Java 8.
Covert Json parser from Gson to Jackson as I don't want to include two Json parsers to my projects.
Remove google collections from dependency list as it is stopped long time ago.
Fix thread safe issue with Java Mac.doFinal call.

Tous les tests unitaires existants ont été acceptés avec les nouveaux cas de tests ajoutés.

Voici un exemple pour générer un jeton et vérifier le jeton. Pour plus d'informations, s'il vous plaît vérifier https://github.com/networknt/light code source d'utilisation.

Je suis l'auteur de jsontoken et du cadre d'application Omni-Channel.

2
Steve Hu