JWT(JSON Web Token)library for Java [关闭]

voj3qocg  于 2023-05-27  发布在  Java
关注(0)|答案(9)|浏览(93)

**已关闭。**此问题正在寻求书籍、工具、软件库等的建议。它不符合Stack Overflow guidelines。目前不接受答复。

我们不允许问题寻求书籍,工具,软件库等的建议。您可以编辑问题,以便可以用事实和引用来回答。
3年前关闭。
Improve this question
我正在使用Java和AngularJS开发一个Web应用程序,并选择实现令牌身份验证和授权。出于练习的目的,我已经到了将凭证发送到服务器、生成随机令牌并存储它并将其发送回客户机的地步。在每次请求服务器时,我都会在头中附加令牌,它工作得很好。对于身份验证的观点是完美的,不需要更多。
但是,我现在想跟踪用户类型(admin,regular user…),以及它的id,或任何其他唯一字段;正如我所理解的,我必须在登录操作期间将其加密在我发送回客户端的令牌中。对吗?
您是否使用过任何可以生成、加密和解密此类令牌的JWT库?如果能提供一个到库的API和Maven依赖项的链接,将不胜感激。
谢谢

eqoofvh9

eqoofvh91#

JJWT旨在成为JVM和Android上最容易使用和理解的JWT库:
https://github.com/jwtk/jjwt

jckbn6z7

jckbn6z73#

通过引用https://jwt.io/,您可以找到许多语言中的jwt实现,包括java。该网站还提供了这些实现之间的一些比较(它们支持的算法和....)。
对于java,这些是提到的库:

qybjjes1

qybjjes14#

这个库看起来很好用: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 Wallet使用。
下面是如何创建一个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

vltsax25

vltsax255#

IETF在其wiki上建议使用Jose libs:http://trac.tools.ietf.org/wg/jose/trac/wiki
我强烈推荐使用它们来签名。我不是一个Java的家伙,但似乎jose 4j似乎是一个不错的选择。也有很好的例子:https://bitbucket.org/b_c/jose4j/wiki/JWS%20Examples
更新:jwt.io提供了几个jwt相关库及其特性的简洁比较。一个必须检查!
我很想听听其他java开发者喜欢什么。

31moq8wy

31moq8wy7#

本页保留了对各种语言(包括Java)实现的引用,并比较了功能:http://kjur.github.io/jsjws/index_mat.html

r7s23pms

r7s23pms8#

如果您只需要解析未签名的未加密令牌,则可以使用以下代码:

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

xkrw2x1b9#

https://github.com/networknt/jsontoken
这是一个原始的谷歌jsontoken的分支
自2012年9月11日以来尚未更新,并且依赖于一些旧软件包。
我所做的:

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的作者。

相关问题