用于Java的JWT(JSON Web Token)库

Mar*_*anu 67 java json token jwt web

我正在开发使用Java和AngularJS开发的Web应用程序,并选择实现令牌认证和授权.出于练习目的,我已经到了将证书发送到服务器,生成随机令牌存储它并将其发送回客户端的程度.在每次向服务器发出请求时,我都会在标头中附加令牌并且它可以正常工作.对于身份验证的观点是完美的,不需要更多.

但是,我现在想要跟踪用户类型(管理员,普通用户......),以及它的id或任何其他唯一字段; 据我所知,我必须在令牌中加密,我在登录操作期间将其发送回客户端.那是对的吗?

您是否使用过任何JWT库并可以生成,加密和解密此类令牌?将非常感谢图书馆的API和Maven依赖关系的链接.

谢谢

Les*_*ood 50

JJWT旨在最简单地使用和理解JVM和Android的JWT库:

https://github.com/jwtk/jjwt

  • 简单,容易和干净,并立即工作.我首先去了谷歌JsonToken,并在弄乱了未解决的依赖关系和代码页以组装一个简单的JWT后切换到这里. (4认同)
  • 关于这一点的警告。有很多人在运行时依赖解析方面遇到问题。我仍然不明白为什么作者不能像其他普通库一样创建该库。我最终使用了其他东西,因为作者一直坚持认为配置是错误的。但我的设置与他在 GitHub 上的设置一模一样。我的项目推迟了几天左右。 (3认同)
  • @LesHazlewood 我正在使用 https://github.com/auth0/java-jwt ,它的效果更好。没有奇怪的深奥地牢巫术。 (3认同)

Mar*_*anu 23

如果有人需要答案,

我使用了这个库:http://connect2id.com/products/nimbus-jose-jwt Maven here:http://mvnrepository.com/artifact/com.nimbusds/nimbus-jose-jwt/2.10.1

  • 请确保您使用最新版本。该库将得到不断的审查和改进,并添加了新的算法/功能:http://mvnrepository.com/artifact/com.nimbusds/nimbus-jose-jwt从3.2版开始,所有标准JWS签名算法也得到了完全支持与所有JWE加密算法一样,除了PBES2和ECDH-ES。 (2认同)

Ali*_*ahi 14

通过参考https://jwt.io/,您可以找到jwt许多语言的实现,包括java.该站点还提供了这些实现(它们支持的算法和......)之间的一些比较.

对于java这些提到的库:

  • @jkerak用你认为最简单的方式来实现.如果所有的实现对你来说似乎都是希腊的,那么请选择最酷的名称.这对我来说效果很好. (2认同)

Mar*_*uez 13

该库似乎运行良好: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>
Run Code Online (Sandbox Code Playgroud)

该库实际上是由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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这基于以下代码: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

  • 这个库使用了1000个依赖项,这些依赖项都需要解析,编译并使项目变得混乱.为什么不主要使用Java中的可用内容? (3认同)

Pri*_*shj 7

IETF在它的维基上建议了jose libs:http: //trac.tools.ietf.org/wg/jose/trac/wiki

我强烈建议使用它们进行签名.我不是一个Java人,但似乎jose4j似乎是个不错的选择.也有很好的例子:https://bitbucket.org/b_c/jose4j/wiki/JWS%20Examples

更新:jwt.io提供了几个jwt相关库及其功能的简洁比较.一定要检查!

我很想知道其他java开发者喜欢什么.


mfi*_*rry 5

我发现这是小而完整的https://github.com/auth0/java-jwt