【问题标题】:Java 8 Base64 JWT token into JSONJava 8 Base64 JWT 令牌转换为 JSON
【发布时间】:2019-10-17 09:00:37
【问题描述】:

所以,我在网上和 StackOverflow 上对此进行了一些研究,并尝试了许多我发现的建议。问题是我正在登录我们运行良好的 Oauth2 服务之一。我得到了一个 Oath2 JWT 令牌。我知道这是 Base64 编码的,我可以将令牌放入 jwt.io 和 www.base64decode.org 并且这两个站点都正确解析令牌。

我使用的是Java 8 Base64工具,代码如下:

public String getTokenProperty(String token, String propertyName)
{
    byte[] bytes = Base64.getUrlDecoder().decode(token);
    String decodedString = new String(bytes, StandardCharsets.UTF_8);
    System.out.println("Decoded: " + decodedString);
    return (new JSONObject(decodedString)).getString(propertyName);
}

decoder线上出现的错误如下:

java.lang.IllegalArgumentException: Illegal base64 character 2e

我用我的 Oauth2 服务的令牌尝试了这个,我从 Syncope 获得了一个令牌,我从 Auth0 获得了一个令牌......所有返回的都是 JWT Base64 编码的令牌。 使用来自这些不同服务器的所有这些令牌,我得到了同样的错误。

我想使用标准的 Java 8 Base64,但我想我可能需要使用外部第三方 Base64 解码器。

任何帮助都会很棒。谢谢!

令牌如下:

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik1qSTRRVFEwT1VRNU9VSXlSVEV6TlRBd05UVXpSVVExTlVOR05FVkVORGRDTlRnM016VXdRZyJ9.eyJodHRwczovL2JpdG9vbXRyYWRlci5uZXQvYXV0aG9yaXphdGlvbiI6eyJncm91cHMiOlsiQ29uc3VtZXJzIl0sInJvbGVzIjpbIlVzZXIiXX0sImlzcyI6Imh0dHBzOi8vYml0em9vbS5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NWNhNTE5NzZjYzMzZjUxMTBhYWNkYmM0IiwiYXVkIjpbImh0dHBzOi8vYml0em9vbS5hdXRoMC5jb20vYXBpL3YyLyIsImh0dHBzOi8vYml0em9vbS5hdXRoMC5jb20vdXNlcmluZm8iXSwiaWF0IjoxNTU5MzIzNDI1LCJleHAiOjE1NTk0MDk4MjUsImF6cCI6IlliRGFSelRVQkFtZEFrSExqdjZ0bEI3U05xSTF1RlNtIiwic2NvcGUiOiJvcGVuaWQgcHJvZmlsZSBlbWFpbCBhZGRyZXNzIHBob25lIHJlYWQ6Y3VycmVudF91c2VyIHVwZGF0ZTpjdXJyZW50X3VzZXJfbWV0YWRhdGEgZGVsZXRlOmN1cnJlbnRfdXNlcl9tZXRhZGF0YSBjcmVhdGU6Y3VycmVudF91c2VyX21ldGFkYXRhIGNyZWF0ZTpjdXJyZW50X3VzZXJfZGV2aWNlX2NyZWRlbnRpYWxzIGRlbGV0ZTpjdXJyZW50X3VzZXJfZGV2aWNlX2NyZWRlbnRpYWxzIHVwZGF0ZTpjdXJyZW50X3VzZXJfaWRlbnRpdGllcyIsImd0eSI6InBhc3N3b3JkIn0.St7097L1ZAlBWcAPrie-8CGV2F3Fr8uNYpSDVKSPVPF4zBZrmm62_UAj7Ssux8AjUy0LhjiF3kLpNph2L7yrpUREw6TyGJwQasfdVtM5VzRYUcy-fOGyRSqPQorbzxJQZzs2pyDJm-2hMQ0McJ37ubKIWrHFD5McMedN6THK7g5TExX47XCRPcOuCEWm3bf3zdWF2LEGhCw_c-lcZDwlb4ePkO721XjSWtrXEBvxc8scFNaHDt7VOnrSze4XK_LO8eE8bHRq6qUrWf1csYucK--aHazBsvfdl-6QDRk-tOBM-LdXJMT7H8Ih6trxVmZofQjr2dQ4j_3DTVoU3eLdog

更新:

我从 java,util.Base64 切换到 org.apache.commons.codec.binary.Base64 这似乎有点工作,我现在没有收到错误。

String decodedString = new String(bytes, StandardCharsets.UTF_8);

返回一串标头、有效负载和签名数据。所以,当我这样做时:

JSONObject jsonObject = new JSONObject(decodedString);
    System.out.println("getTokenProperty: jsonObject = " + jsonObject.toString());

我只是取回头部数据,我真正需要的是有效载荷。

为了记录......我从“概念证明”项目继承的代码是:

public static String getTokenProperty(String token, String propertyName)
{
    return (new JSONObject(new String(Base64.getDecoder().decode(token)))).getString(propertyName);
}

根本没有单元测试。所以,当我去单元测试它时,它当然完全坏了。所以,现在我对如何解析这个token有了更好的理解,这节课我会记很久的。

非常感谢!

【问题讨论】:

  • 好的,我添加了从 Auth0 生成的令牌。我还从 java.util.Base64 切换到了 org.apache.commons.codec.binary.Base64,它实际上确实可以工作,并且我获得了标头、有效负载和签名的 JSON 数据,但之后我也得到了很多垃圾。 ..不确定那是什么。当我到达获得 JSONObject 的第三行时,我只获得了标题,我真的想要有效负载数据。
  • @Brandon 那个令牌来自哪里?
  • @shmosel;我修复了令牌.. ideone.com/IUfTYH
  • 我发布的令牌来自 Auth0 的测试帐户。那是他们的真实标记,我在解析它时遇到了同样的错误。是的,我带着你提供的样本去了那个页面,是的,我同意代码可以工作......但令牌也在那个样本中被硬编码。该代码,带有来自 Auth0 的令牌的标准 java 代码实际上不起作用!
  • 当我使用 Base64.getMimeDecoder() 而不是 Base64.getUrlDecoder() 时,我没有遇到异常。不过,我也确实得到了尾随的二进制数据。

标签: java java-8 jwt base64url


【解决方案1】:

它不解析的原因是因为您正在尝试 Base64URLDecode 整个令牌。但是您必须解码由点“。”分隔的令牌的部分。字符(十六进制的 0x2e,十进制的 46,html 中的 . -- ASCII/UTF8)..

例子:

public static void decodeTokenParts(String token)
{
    String[] parts = token.split("\\.", 0);

    for (String part : parts) {
        byte[] bytes = Base64.getUrlDecoder().decode(part);
        String decodedString = new String(bytes, StandardCharsets.UTF_8);

        System.out.println("Decoded: " + decodedString);
    }
}

这是因为 JWT 令牌由多个部分组成:

例如Base64URLEncode({HeaderJSON}) + "." + Base64URLEncode({PayloadJSON}) + "." + Signature..

所以要解码它..你需要用“。”来分割它。并解码每个部分。注意:签名通常是二进制编码为base64,所以一旦你解码它,不要尝试打印它..它会打印字节。您需要验证签名。

例如,如果你去:https://jwt.io/#debugger-io?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

您将看到每个“部分”是如何编码的。它是彩色编码的。

【讨论】:

  • 是的,我对JWT.io很熟悉,之前也用过。我只是最近没有在 Java 中解析过 JWT 令牌。我最后一次使用 Base64 是对图像进行编码。但这确实解决了我的问题。
  • @tjholmes66;很好 :) 我不确定,所以无论如何我都包含了 jwt.io 链接,以便将来其他人也更容易理解。
  • 太棒了!对我来说是一个简单的愚蠢问题。但重要的是我学到了,我希望这对其他人有帮助!!!
  • No such property: StandardCharsets for class: Script1??
【解决方案2】:

我使用这个库https://mvnrepository.com/artifact/com.auth0/java-jwt/3.12.0 进行解码以获取主题(userId):JWT.decode(token).getSubject()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-12
    • 2013-06-28
    • 1970-01-01
    • 2017-05-09
    • 2019-07-13
    • 2012-11-20
    • 2015-10-30
    • 2019-06-03
    相关资源
    最近更新 更多