在 vert.x 中获取用户并验证 JWT 令牌

Posted

技术标签:

【中文标题】在 vert.x 中获取用户并验证 JWT 令牌【英文标题】:Get user and validate JWT token in vert.x 【发布时间】:2017-10-21 19:11:57 【问题描述】:

我已经建立了一个 keycloak 服务器,并且我正在开发一个将在互联网上发布的 API。 API 将接收第三方(客户端)的调用。这些客户端将首先使用 clientId 和 secret 调用 keycloak 服务器以获取令牌,然后他们将使用此令牌调用我的 API。

我需要看看如何解析和验证这个令牌。此令牌可能是 JWT。 因此,在我的测试用例中,我有一个 HTTP 请求,其标头中有一个 json Web 令牌。令牌由在 localhost 中启动的 keycloak 提供。我已经复制了整个令牌:

"Authorization":"Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJGSjg2R2NGM2pUYk5MT2NvNE52WmtVQ0lVbWZZQ3FvcXRPUWVNZmJoTmxFIn0.eyJqdGkiOiI2YWZlZjBiMC03ZmQ1LTRiOWUtOTk3NC0yOGFjMzBkMGM5OWQiLCJleHAiOjE0OTU2MTA0NTQsIm5iZiI6MCwiaWF0IjoxNDk1NjEwMTU0LCJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjgxMDAvYXV0aC9yZWFsbXMvZXhhbXBsZSIsImF1ZCI6ImpzLWNvbnNvbGUiLCJzdWIiOiJjNGY4NjE0Zi02YjFlLTRlYjItYmYxZC0wOTJmNGYxNWQwYmIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJqcy1jb25zb2xlIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiNTQ4NDJjNTgtMzYxYi00MDk2LThhNjgtNGZkZTg5OGUwNzg5IiwiYWNyIjoiMSIsImNsaWVudF9zZXNzaW9uIjoiNDNjMWEzMjAtNGZmNi00NmRmLThmZjUtNTU2ZjgxNGZhYzk1IiwiYWxsb3dlZC1vcmlnaW5zIjpbXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbInVzZXIiXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJuYW1lIjoiU2FtcGxlIFVzZXIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ1c2VyIiwiZ2l2ZW5fbmFtZSI6IlNhbXBsZSIsImZhbWlseV9uYW1lIjoiVXNlciIsImVtYWlsIjoic2FtcGxlLXVzZXJAZXhhbXBsZSJ9.n1K0KIGYJYPZkjSq1eSg5gWnCAj44mgl4M-GJOlzgCj8y5TGw5OhT7sr84o9Ja9K6WMW3t0ti6feZIgc8mps3RK0HuuXeCNcrN6H2dPEtBphTvfXEUR2iMg83iCmxjhXgXso7oX2vyreJqB6WCCFEPbAQH2e5kHZqv6cfmXRlYU"

我想:

解析令牌 获取我需要的键/值对 在 keycloak 服务器中验证令牌。

目标是保护其余服务并授予对特定角色的访问权限。 我的应用程序是带有路由的 3.4.1 vert.x。

我现在有一个我发现的设置 JWTAuthHandler 的示例

    JWTAuth authProvider = JWTAuth.create(vertx, config().getJsonObject("keycloak.oidc"));
    router.route("/protected/*").handler(JWTAuthHandler.create(authProvider));

    router.route("/protected/somepage").handler(ctx -> 
        logger.info("Headers: ", ctx.request().headers().get("Authorization"));
        logger.info(ctx.user().principal().encodePrettily());
    );

来自我的 API(用于 JWTAuth)的调用的 Keycloak 配置是:

   "keycloak.oidc": 
    "realm": "myrealm",
    "auth-server-url": "http://localhost:8100/auth",
    "ssl-required": "none",
    "resource": "app-client",
    "public-client": true

当我在邮递员中进行其余调用时,jvm 并没有真正设法进入处理程序并记录标头,它会立即抛出此异常 说 io.vertx.ext.web.handler.impl.JWTAuthHandlerImpl AVERTISSEMENT: JWT decode failure java.lang.RuntimeException: Not enough or too many segments

【问题讨论】:

您收到的错误是告诉您收到的令牌不是有效的 JWT,因为 JWT 至少需要 2 个段。有关这些部分的详细信息,请参阅:jwt.io,因为它为您提供了有关其工作方式的良好视觉反馈。我猜你得到的不仅仅是 JWT String[] 段数组由 3 个段组成(我处于调试模式)。我还在 jwt.io 上检查过。我不知道它有什么问题。 我需要在通话中添加任何证书或公钥/私钥吗?现在,在我的 API 中,我使用以下客户端配置调用 keycloak:` "keycloak.oidc": "realm": "myrealm", "auth-server-url": "localhost:8100/auth", "ssl-required" :“无”,“资源”:“应用程序客户端”,“公共客户端”:true ` 配置不正确,我们有一个拉取请求,要求它严格输入,但同时你可以看到这个完全工作的例子:github.com/openshiftio-vertx-boosters/… 【参考方案1】:

如果我理解正确,您有一个 API 可以在标头中使用 JWT 发出请求。

在这种情况下,您不应使用 OAuth2 处理程序,而应使用 JWT handler。此处理程序可以与来自 keycloak 的read only tokens 一起使用。

重要的是要知道,与任何其他 Auth 处理程序一样,如果请求通过验证,您将获得一个 User 对象。这个对象可以用来执行authorization assertions。或者,如果您对令牌的原始 JSON 表示感兴趣,您可以将其解读为:

JsonObject token = context.user().principal();

您可以随意检查它。

【讨论】:

我已经建立了一个 keycloak 服务器,我正在开发 API。我会接到第三方的电话。这些第三方将首先调用 keycloak 服务器来获取令牌,然后他们将使用令牌调用我的 API。我需要看看如何解析和验证这个令牌 感谢您的代码,我将代码修改为:JWTAuth authProvider = JWTAuth.create(vertx, config().getJsonObject("keycloak.oidc")); router.route("/protected/*").handler(JWTAuthHandler.create(authProvider)); router.route("/protected/somepage").handler(ctx -> String theSubject = ctx.user().principal().getString("sub"); String someKey = ctx.user().principal().getString("someKey"); ); ctx.user() 在我的情况下为 null 如上所述,如何获取在标头中找到的 JWT 的解码数据? 我相信你应该提供一个例子来展示你的代码。鉴于您的处理程序已执行,用户不应为 null,因为它应包含令牌的内容。 自从我的发展演变以来,我在帖子中更新了很多内容。请检查一下,不要犹豫回复。我了解到您是 JWTAuth 的开发者,谢谢【参考方案2】:

您现在的操作方式将尝试自动验证您的身份。 如果您想做一些手动步骤,请使用authProvider.getToken

见官方例子:https://github.com/vert-x3/vertx-auth/blob/master/vertx-auth-oauth2/src/main/java/examples/AuthOAuth2Examples.java#L196

【讨论】:

【参考方案3】:

我查看了 JWTAuthProviderImpl 的源代码,我意识到我需要在配置中提供公钥。所以我刚刚将它添加到我的 keycloak 配置中:

"public-key": "MypublickeyblablablavOCAQ8AMvdsvseee"

【讨论】:

以上是关于在 vert.x 中获取用户并验证 JWT 令牌的主要内容,如果未能解决你的问题,请参考以下文章

如何在Vert.x REST服务中转发jwt令牌

在视图或消费者中使用 jwt 令牌验证并获取用户

Firebase php-jwt 令牌刷新

在微服务架构的每个服务中验证访问令牌 (JWT)

在永久存储中跟踪 JWT

如何从 JWT 令牌中获取用户 ID