如何在android中解码JWT令牌?

时间:2016-06-08 07:26:19

标签: java android jwt

我有一个像这样的jwt令牌

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

如何对此进行解码,以便我可以像这样获得有效载荷

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

我使用过this库,但找不到办法做我想做的事情

7 个答案:

答案 0 :(得分:33)

你应该拆分字符串: 如果您通过base 64解码器传递前两个部分,您将获得以下内容(为清晰起见,添加了格式):

{
  "alg": "HS256",
  "typ": "JWT"
}

    {
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

代码示例:

public class JWTUtils {

    public static void decoded(String JWTEncoded) throws Exception {
        try {
            String[] split = JWTEncoded.split("\\.");
            Log.d("JWT_DECODED", "Header: " + getJson(split[0]));
            Log.d("JWT_DECODED", "Body: " + getJson(split[1]));
        } catch (UnsupportedEncodingException e) {
            //Error
        }
    }

    private static String getJson(String strEncoded) throws UnsupportedEncodingException{
        byte[] decodedBytes = Base64.decode(strEncoded, Base64.URL_SAFE);
        return new String(decodedBytes, "UTF-8");
    }
}

调用方法例如

JWTUtils.decoded("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ");

库参考: https://github.com/jwtk/jjwt

jwt测试: https://jwt.io/

答案 1 :(得分:3)

我使用了名为JWTDecode.Android https://github.com/auth0/JWTDecode.Android的第三方库。文档相当不错。根据您的问题,子,名称等是身体的一部分,称为声明。你可以使用上面的库得到它们:

  JWT parsedJWT = new JWT(jwtToken);
  Claim subscriptionMetaData = parsedJWT.getClaim("name");
  String parsedValue = subscriptionMetaData.asString();

答案 2 :(得分:1)

我在Java Web应用程序中使用过,代码如下所示: -

Jwts.parser().setSigningKey('secret-key').parseClaimsJws(token).getBody()

它将返回包含所需值的声明。

答案 3 :(得分:0)

这可以使用Java 8的Base64类:

public String getDecodedJwt(String jwt)
{
  String result = "";

  String[] parts = jwt.split("[.]");
  try
  {
    int index = 0;
    for(String part: parts)
    {
      if (index >= 2)
        break;

      index++;
      byte[] partAsBytes = part.getBytes("UTF-8");
      String decodedPart = new String(java.util.Base64.getUrlDecoder().decode(partAsBytes), "UTF-8");

      result += decodedPart;
    }
  }
  catch(Exception e)
  {
    throw new RuntimeException("Couldnt decode jwt", e);
  }

  return result;
}

答案 4 :(得分:0)

如果项目已经在使用AWSCognito SDK,则可以使用CognitoJWTParser类。 它具有静态方法getHeader()getPayload()getSignature()

https://github.com/aws-amplify/aws-sdk-android/blob/master/aws-android-sdk-cognitoidentityprovider/src/main/java/com/amazonaws/mobileconnectors/cognitoidentityprovider/util/CognitoJWTParser.java

答案 5 :(得分:0)

部分基于Brad Parks提供的代码,通过使用Apache Commons使其适用于较低版本的Android,并转换为Kotlin:

build.gradle中:

implementation 'apache-codec:commons-codec:1.2'

在Kotlin课堂上:

fun decodeToken(token: String): String{
    val tokenParts: Array<String> = token.split(".").toTypedArray()
    if(tokenParts.isEmpty()) return token
    var decodedString = ""
    for(part: String in tokenParts){
        val partByteArray: ByteArray =
            stringToFullBase64EncodedLength(part).toByteArray(Charsets.US_ASCII)
        val decodedPart = String(Base64.decodeBase64(partByteArray))
        decodedString+=decodedPart
        // There are a maximum of two parts in an OAuth token,
        // and arrays are 0-indexed, so if the index is 1
        // we have processed the second part and should break.
        if(tokenParts.indexOf(part) == 1) break
    }
    return decodedString
}

private fun stringToFullBase64EncodedLength(string: String): String{

    // A properly base64 encoded string must be divisible by 4
    // We'll pad it to the nearest multiple of 4 without losing data:
    val targetLength: Int = ( 4 * ceil( string.length.toDouble()/4 ) ).toInt()

    // Now, we get the difference, and add it with a reserved character (`=`)
    // to the end of the string. It will get removed later.
    val requiredPadding: Int =  targetLength-string.length
    return string+"=".repeat(requiredPadding)

}

答案 6 :(得分:0)

Android SDK 26+ (Oreo) 的 Kotlin 无依赖版本:

fun extractJwt(jwt: String): String {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return "Requires SDK 26"
    val parts = jwt.split(".")
    return try {
        val charset = charset("UTF-8")
        val header = String(Base64.getUrlDecoder().decode(parts[0].toByteArray(charset)), charset)
        val payload = String(Base64.getUrlDecoder().decode(parts[1].toByteArray(charset)), charset)
        "$header\n$payload"
    } catch (e: Exception) {
        "Error parsing JWT: $e"
    }
}