在 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 令牌的主要内容,如果未能解决你的问题,请参考以下文章