在 vert.x 中获取用户并验证 JWT 令牌
Get user and validate JWT token in vert.x
我已经设置了一个 keycloak 服务器,我正在开发一个 API,它将在 Internet 上发布。 API 将接听第三方(客户)的电话。这些客户端将首先使用 clientId 和秘密调用 keycloak 服务器以获取令牌,然后他们将使用此令牌调用我的 API。
我需要了解如何解析和验证此令牌。此令牌可能是 JWT。
因此,在我的测试用例中,我有一个 http 请求,在 header 中有一个 json 网络令牌。令牌由在本地主机中启动的 keycloak 提供。我已经复制了整个令牌:
{"Authorization":"Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJGSjg2R2NGM2pUYk5MT2NvNE52WmtVQ0lVbWZZQ3FvcXRPUWVNZmJoTmxFIn0.eyJqdGkiOiI2YWZlZjBiMC03ZmQ1LTRiOWUtOTk3NC0yOGFjMzBkMGM5OWQiLCJleHAiOjE0OTU2MTA0NTQsIm5iZiI6MCwiaWF0IjoxNDk1NjEwMTU0LCJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjgxMDAvYXV0aC9yZWFsbXMvZXhhbXBsZSIsImF1ZCI6ImpzLWNvbnNvbGUiLCJzdWIiOiJjNGY4NjE0Zi02YjFlLTRlYjItYmYxZC0wOTJmNGYxNWQwYmIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJqcy1jb25zb2xlIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiNTQ4NDJjNTgtMzYxYi00MDk2LThhNjgtNGZkZTg5OGUwNzg5IiwiYWNyIjoiMSIsImNsaWVudF9zZXNzaW9uIjoiNDNjMWEzMjAtNGZmNi00NmRmLThmZjUtNTU2ZjgxNGZhYzk1IiwiYWxsb3dlZC1vcmlnaW5zIjpbXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbInVzZXIiXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJuYW1lIjoiU2FtcGxlIFVzZXIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ1c2VyIiwiZ2l2ZW5fbmFtZSI6IlNhbXBsZSIsImZhbWlseV9uYW1lIjoiVXNlciIsImVtYWlsIjoic2FtcGxlLXVzZXJAZXhhbXBsZSJ9.n1K0KIGYJYPZkjSq1eSg5gWnCAj44mgl4M-GJOlzgCj8y5TGw5OhT7sr84o9Ja9K6WMW3t0ti6feZIgc8mps3RK0HuuXeCNcrN6H2dPEtBphTvfXEUR2iMg83iCmxjhXgXso7oX2vyreJqB6WCCFEPbAQH2e5kHZqv6cfmXRlYU"}
我想:
- 解析令牌
- 获得我需要的 key/value 对
- 验证密钥斗篷服务器中的令牌。
目标是保护其余服务并授予特定角色访问权限。
我的应用程序是带有路由的 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 调用的 Keycloak 配置(用于 JWTAuth)是:
"keycloak.oidc": {
"realm": "myrealm",
"auth-server-url": "http://localhost:8100/auth",
"ssl-required": "none",
"resource": "app-client",
"public-client": true
}
当我在邮递员中进行其余调用时,jvm 并没有真正设法进入处理程序并记录 headers,但它立即抛出此异常
说
io.vertx.ext.web.handler.impl.JWTAuthHandlerImpl
AVERTISSEMENT: JWT decode failure java.lang.RuntimeException: Not enough or too many segments
您现在执行此操作的方式将尝试自动对您进行身份验证。
如果您想执行一些手动步骤,请使用 authProvider.getToken
如果我理解正确的话,你有一个 API 向 headers 中的 JWT 发出请求。
在这种情况下,您不应使用 OAuth2 处理程序,而应使用 keycloak 中的 JWT handler. This handler can be used with read only tokens。
重要的是要知道,与任何其他 Auth
处理程序一样,如果请求通过验证,您将获得 User
object。这个object可以用来执行authorization assertions。或者,如果您对令牌的原始 JSON 表示形式感兴趣,您可以将其解读为:
JsonObject token = context.user().principal();
在那里你可以随意检查它。
我查看了 JWTAuthProviderImpl 的源代码,我意识到我需要在配置中提供 public 键。所以我刚刚将它添加到我的 keycloak 配置中:
"public-key": "MypublickeyblablablavOCAQ8AMvdsvseee"
我已经设置了一个 keycloak 服务器,我正在开发一个 API,它将在 Internet 上发布。 API 将接听第三方(客户)的电话。这些客户端将首先使用 clientId 和秘密调用 keycloak 服务器以获取令牌,然后他们将使用此令牌调用我的 API。
我需要了解如何解析和验证此令牌。此令牌可能是 JWT。 因此,在我的测试用例中,我有一个 http 请求,在 header 中有一个 json 网络令牌。令牌由在本地主机中启动的 keycloak 提供。我已经复制了整个令牌:
{"Authorization":"Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJGSjg2R2NGM2pUYk5MT2NvNE52WmtVQ0lVbWZZQ3FvcXRPUWVNZmJoTmxFIn0.eyJqdGkiOiI2YWZlZjBiMC03ZmQ1LTRiOWUtOTk3NC0yOGFjMzBkMGM5OWQiLCJleHAiOjE0OTU2MTA0NTQsIm5iZiI6MCwiaWF0IjoxNDk1NjEwMTU0LCJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjgxMDAvYXV0aC9yZWFsbXMvZXhhbXBsZSIsImF1ZCI6ImpzLWNvbnNvbGUiLCJzdWIiOiJjNGY4NjE0Zi02YjFlLTRlYjItYmYxZC0wOTJmNGYxNWQwYmIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJqcy1jb25zb2xlIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiNTQ4NDJjNTgtMzYxYi00MDk2LThhNjgtNGZkZTg5OGUwNzg5IiwiYWNyIjoiMSIsImNsaWVudF9zZXNzaW9uIjoiNDNjMWEzMjAtNGZmNi00NmRmLThmZjUtNTU2ZjgxNGZhYzk1IiwiYWxsb3dlZC1vcmlnaW5zIjpbXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbInVzZXIiXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJuYW1lIjoiU2FtcGxlIFVzZXIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ1c2VyIiwiZ2l2ZW5fbmFtZSI6IlNhbXBsZSIsImZhbWlseV9uYW1lIjoiVXNlciIsImVtYWlsIjoic2FtcGxlLXVzZXJAZXhhbXBsZSJ9.n1K0KIGYJYPZkjSq1eSg5gWnCAj44mgl4M-GJOlzgCj8y5TGw5OhT7sr84o9Ja9K6WMW3t0ti6feZIgc8mps3RK0HuuXeCNcrN6H2dPEtBphTvfXEUR2iMg83iCmxjhXgXso7oX2vyreJqB6WCCFEPbAQH2e5kHZqv6cfmXRlYU"}
我想:
- 解析令牌
- 获得我需要的 key/value 对
- 验证密钥斗篷服务器中的令牌。
目标是保护其余服务并授予特定角色访问权限。 我的应用程序是带有路由的 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 调用的 Keycloak 配置(用于 JWTAuth)是:
"keycloak.oidc": {
"realm": "myrealm",
"auth-server-url": "http://localhost:8100/auth",
"ssl-required": "none",
"resource": "app-client",
"public-client": true
}
当我在邮递员中进行其余调用时,jvm 并没有真正设法进入处理程序并记录 headers,但它立即抛出此异常
说
io.vertx.ext.web.handler.impl.JWTAuthHandlerImpl
AVERTISSEMENT: JWT decode failure java.lang.RuntimeException: Not enough or too many segments
您现在执行此操作的方式将尝试自动对您进行身份验证。
如果您想执行一些手动步骤,请使用 authProvider.getToken
如果我理解正确的话,你有一个 API 向 headers 中的 JWT 发出请求。
在这种情况下,您不应使用 OAuth2 处理程序,而应使用 keycloak 中的 JWT handler. This handler can be used with read only tokens。
重要的是要知道,与任何其他 Auth
处理程序一样,如果请求通过验证,您将获得 User
object。这个object可以用来执行authorization assertions。或者,如果您对令牌的原始 JSON 表示形式感兴趣,您可以将其解读为:
JsonObject token = context.user().principal();
在那里你可以随意检查它。
我查看了 JWTAuthProviderImpl 的源代码,我意识到我需要在配置中提供 public 键。所以我刚刚将它添加到我的 keycloak 配置中:
"public-key": "MypublickeyblablablavOCAQ8AMvdsvseee"