programing

자바 용 JWT (JSON 웹 토큰) 라이브러리

nasanasas 2020. 11. 11. 20:15
반응형

자바 용 JWT (JSON 웹 토큰) 라이브러리


Java 및 AngularJS를 사용하여 개발 된 웹 응용 프로그램을 작업 중이며 토큰 인증 및 권한 부여를 구현하기로 선택했습니다. 연습 목적으로 서버에 자격 증명을 보내고 임의의 토큰을 생성하여 저장 한 다음 클라이언트로 다시 보내는 지점에 도달했습니다. 서버에 대한 모든 요청에서 헤더에 토큰을 첨부하고 완벽하게 작동합니다. 인증 관점은 완벽하며 더 이상 필요하지 않습니다.

그러나 이제 사용자 유형 (관리자, 일반 사용자 ...)뿐만 아니라 ID 또는 기타 고유 필드를 추적하고 싶습니다. 로그인 작업 중에 클라이언트로 다시 보내는 토큰에서 암호화해야 함을 이해했습니다. 그 맞습니까?

이러한 토큰을 사용하고 생성, 암호화 및 복호화 할 수있는 JWT 라이브러리가 있습니까? 라이브러리의 API 및 Maven 종속성에 대한 링크를 많이 주시면 감사하겠습니다.

감사


JJWT는 JVM 및 Android 용 JWT 라이브러리를 가장 쉽게 사용하고 이해하는 것을 목표로합니다.

https://github.com/jwtk/jjwt


답변이 필요한 사람이 있다면

이 라이브러리를 사용했습니다. http://connect2id.com/products/nimbus-jose-jwt Maven 여기 : http://mvnrepository.com/artifact/com.nimbusds/nimbus-jose-jwt/2.10.1


를 참조하여 https://jwt.io/ 찾을 수 jwt등 많은 언어로 구현 java. 또한 사이트는 이러한 구현 (그들이 지원하는 알고리즘과 ....) 간의 비교를 제공합니다.

들어 java이 언급 한 라이브러리는 다음과 같습니다


이 라이브러리는 잘 작동하는 것 같습니다 : 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 = "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


IETF has suggested jose libs on it's wiki: http://trac.tools.ietf.org/wg/jose/trac/wiki

I would highly recommend using them for signing. I am not a Java guy, but seems like jose4j seems like a good option. Has nice examples as well: https://bitbucket.org/b_c/jose4j/wiki/JWS%20Examples

Update: jwt.io provides a neat comparison of several jwt related libraries, and their features. A must check!

I would love to hear about what other java devs prefer.


I found this to be small and complete https://github.com/auth0/java-jwt


This page keeps references to implementations in various languages, including Java, and compares features: http://kjur.github.io/jsjws/index_mat.html


https://github.com/networknt/jsontoken

This is a fork of original google jsontoken

It has not been updated since Sep 11, 2012 and depends on some old packages.

What I have done:

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.

All existing unit tests passed along with some newly added test cases.

Here is a sample to generate token and verify the token. For more information, please check https://github.com/networknt/light source code for usage.

I am the author of both jsontoken and Omni-Channel Application Framework.


If you only need to parse unsigned unencrypted tokens you could use this 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;
}

참고URL : https://stackoverflow.com/questions/23808460/jwt-json-web-token-library-for-java

반응형