Подтвердить что ты не робот

Библиотека JWT (JSON Web Token) для Java

Я работаю над веб-приложением, разработанным с использованием Java и AngularJS, и решил реализовать аутентификацию и авторизацию токенов. Для целей упражнений я пришел к тому, что я отправляю учетные данные на сервер, создаю случайный токен, чтобы сохранить его и отправить обратно клиенту. При каждом запросе на сервер я прикрепляю токен в заголовке, и он отлично работает. Для аутентификации точка зрения идеальна и не нужна больше.

Однако теперь я хочу отслеживать тип пользователя (admin, обычный пользователь...), а также идентификатор или любое другое уникальное поле; как я понял, мне нужно зашифровать это в токене, который я отправляю клиенту во время действия входа в систему. Это правильно?

Существует ли библиотека JWT, которую вы использовали, и можете генерировать, шифровать и расшифровывать такие маркеры? Ссылка на библиотечный API и зависимость от Maven будет очень оценена.

Спасибо

4b9b3361

Ответ 2

JJWT стремится быть самым простым в использовании и понимании JWT-библиотеки для JVM и Android:

https://github.com/jwtk/jjwt

Ответ 3

Эта библиотека работает хорошо: https://code.google.com/p/jsontoken/.

Это зависит от Google Guava. Вот артефакты 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>

Библиотека фактически используется Google Кошельком.

Вот как создать jwt, и проверить его и десериализировать:

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 = "[email protected]^($%*$%";

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

Здесь приведен код: https://developers.google.com/wallet/instant-buy/about-jwts И здесь: https://code.google.com/p/wallet-online-sample-java/source/browse/src/com/google/wallet/online/jwt/util/WalletOnlineService.java?r=08b3333bd7260b20846d7d96d3cf15be8a128dfa

Ответ 4

Обращаясь к https://jwt.io/, вы можете найти реализации jwt на многих языках, включая java. Также сайт обеспечивает некоторое сравнение между этими реализациями (алгоритмы, которые они поддерживают, и....).

Для java это упомянутые библиотеки:

Ответ 5

IETF предложил jose libs на ней wiki: http://trac.tools.ietf.org/wg/jose/trac/wiki

Я очень рекомендую использовать их для подписания. Я не парень Java, но похоже, что jose4j кажется хорошим вариантом. Имеются также хорошие примеры: https://bitbucket.org/b_c/jose4j/wiki/JWS%20Examples

Обновление: jwt.io обеспечивает аккуратное сравнение нескольких связанных с jwt библиотеки и их функции. Обязательно проверьте!

Мне бы хотелось услышать о том, что другие разработчики java предпочитают.

Ответ 7

https://github.com/networknt/jsontoken

Это вилка оригинального google jsontoken

Он не обновлялся с 11 сентября 2012 года и зависит от некоторых старых пакетов.

Что я сделал:

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.

Все существующие модульные тесты прошли вместе с некоторыми недавно добавленными тестовыми примерами.

Вот пример, чтобы сгенерировать токен и проверить токен. Для получения дополнительной информации, пожалуйста, проверьте https://github.com/networknt/light исходный код для использования.

Я являюсь автором как jsontoken, так и Omni-Channel Application Framework.

Ответ 8

Эта страница хранит ссылки на реализации на разных языках, включая Java, и сравнивает функции: http://kjur.github.io/jsjws/index_mat.html

Ответ 9

Если вам нужно только разобрать беззнаковые незашифрованные токены, вы можете использовать этот код:

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