Java 如何在android中解码JWT令牌?

Java 如何在android中解码JWT令牌?,java,android,jwt,Java,Android,Jwt,我有一个这样的令牌 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ { "sub": "1234567890", "name": "John Doe", "admin": true } 我如何解码它,这样我就能得到这样的有效载荷 e

我有一个这样的令牌

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}
我如何解码它,这样我就能得到这样的有效载荷

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

我已经使用了library,但是找不到一种方法来实现我想要的功能,我已经在Java web应用程序中使用过,代码如下所示:-

Jwts.parser().setSigningKey('secret-key').parseClaimsJws(token).getBody()
它将返回包含所需值的声明。

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

标题

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

代码示例:

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");
图书馆参考资料:

jwt测试:
我使用了一个名为JWTDecode.Android的第三方库。文件相当好。根据您的问题,子项、名称等是主体的一部分,称为索赔。您可以使用上面的库获取它们:

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

这使用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;
}

如果项目已经在使用awscognitosdk,那么可以使用
CognitoJWTParser
类。 它有静态方法
getHeader()
getPayload()
getSignature()


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

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)

}
token(token:String):String{
val tokenParts:Array=token.split(“.”).toTypedArray()
if(tokenParts.isEmpty())返回令牌
var decodedString=“”
for(部分:标记部分中的字符串){
val partByteArray:ByteArray=
stringToFullBase64EncodedLength(部分).toByteArray(字符集.US_ASCII)
val decodedPart=String(Base64.decodeBase64(partByteArray))
decodedString+=decodedPart
//OAuth令牌中最多有两个部分,
//和数组的索引为0,因此如果索引为1
//我们已经处理了第二部分,应该中断。
如果(部分)==1)中断
}
返回解码字符串
}
private fun stringToFullBase64EncodedLength(字符串:字符串):字符串{
//正确的base64编码字符串必须可以被4整除
//我们将在不丢失数据的情况下将其填充到4的最接近倍数:
val targetLength:Int=(4*ceil(string.length.toDouble()/4)).toInt()
//现在,我们得到差异,并将其与保留字符(`=`)相加
//到字符串的结尾。稍后将删除它。
val requiredPadding:Int=targetLength-string.length
返回字符串+“=”。重复(需要填充)
}

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

jwt(jwt:String):String{
if(Build.VERSION.SDK_INT
问题在于,is仅在API26@angryITguy不应该这样。因为不同库的其他答案也是正确的。这个图书馆使它更容易。