【问题标题】:How can I decode JWT token in android?如何在 android 中解码 JWT 令牌?
【发布时间】:2016-10-08 07:56:21
【问题描述】:

我有一个像这样的jwt 令牌

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

我怎样才能解码这个,这样我才能得到这样的有效载荷

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

我用过this library,但找不到我想做的方法

【问题讨论】:

    标签: java android jwt


    【解决方案1】:

    如果您使用库io.jsonwebtoken.Jwts,则使用以下sn-p。它对我有用。

    try {
            val claims: Claims =
                Jwts.parser().setSigningKey(secretKey.toByteArray()).parseClaimsJws(token).body
            return ConnectionClaim(claims["uid"].toString(), claims["key"].toString())
    
     } catch (e: JwtException) {
            e.printStackTrace()
     }
    

    【讨论】:

      【解决方案2】:

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

      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"
          }
      }
      

      【讨论】:

        【解决方案3】:

        部分基于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)
        
        }
        

        【讨论】:

          【解决方案4】:

          如果项目已经在使用 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】:

            你应该拆分字符串: 如果您通过 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/

            【讨论】:

              【解决方案6】:

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

              【讨论】:

              • 这个问题是它只适用于 API 26
              【解决方案7】:

              我使用了一个名为 JWTDecode.Android https://github.com/auth0/JWTDecode.Android 的第三方库。文档相当不错。从您的问题来看, sub 、 name 等是 body 的一部分,称为 Claims 。你可以使用上面的库来获得它们:

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

              【讨论】:

              • @angryITguy 这不应该是这样。因为不同库的其他答案也是正确的。这个库使它更容易。
              【解决方案8】:

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

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

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

              【讨论】:

                猜你喜欢
                • 2016-11-15
                • 2021-03-24
                • 2017-04-16
                • 2021-12-30
                • 2018-10-05
                • 2017-04-11
                • 2020-02-02
                • 1970-01-01
                相关资源
                最近更新 更多