Библиотека JWT (JSON Web Token) для Java
Я работаю над веб-приложением, разработанным с использованием Java и AngularJS, и решил реализовать аутентификацию и авторизацию токенов.
Для выполнения упражнения я дошел до того, что отправляю учетные данные на сервер, генерирую случайный токен, сохраняю его и отправляю обратно клиенту.
При каждом запросе к серверу я прикрепляю маркер в заголовке, и он отлично работает.
Для аутентификации точка зрения идеальна и не нуждалась бы в большем.
однако, я сейчас хотите отслеживать тип пользователя (администратор, обычный пользователь...), а также это идентификатор или любое другое уникальное поле; как я понял, я должен зашифровать это в токене, который я отправляю обратно клиенту во время действия входа в систему. Это правильно?
есть ли библиотека JWT, которую вы использовали и можете генерировать, шифровать и расшифровывать такие токены?
Ссылка на API библиотеки и зависимость Maven была бы очень признательна.
спасибо
9 ответов:
Если кто-то в ответ,
Я использовал эту библиотеку: http://connect2id.com/products/nimbus-jose-jwt Maven здесь:http://mvnrepository.com/artifact/com.nimbusds/nimbus-jose-jwt/2.10.1
эта библиотека, кажется, работает хорошо: https://code.google.com/p/jsontoken/ .
это зависит от Google Guava. Здесь представлены артефакты Мэйвен:
<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 = "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; } }это основано на коде здесь: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
ссылаясь на https://jwt.io/ Вы можете найти
jwtреализации на многих языках, включаяjava. Также сайт предоставляет некоторое сравнение между этими реализациями (алгоритмы, которые они поддерживают и т. д.)....).на
javaэто упомянутые библиотеки:
IETF предложил Хосе либс на его Вики: http://trac.tools.ietf.org/wg/jose/trac/wiki
Я настоятельно рекомендую использовать их для подписания. Я не Java парень, но кажется, что jose4j кажется хорошим вариантом. Есть хорошие примеры, а также:https://bitbucket.org/b_c/jose4j/wiki/JWS%20Examples
обновление: jwt.io обеспечивает аккуратное сравнение нескольких связанных jwt библиотеки и их функции. Обязательно чек!
Я хотел бы услышать о том, что предпочитают другие Java-разработчики.
Я обнаружил, что это маленький и полный https://github.com/auth0/java-jwt
эта страница содержит ссылки на реализации на различных языках, включая Java, и сравнивает функции:http://kjur.github.io/jsjws/index_mat.html
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.
Если вам нужно только разобрать неподписанные незашифрованные токены, вы можете использовать этот код:
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; }
Comments