我正在尝试为学习目的构建一个简单的 vert.x 4 中的 Web 应用程序,它需要身份验证和授权才能访问特定资源。我在 webapp 的同一台机器上部署了 keycloak。这是使用 keycloak 保护路由配置:
Router router = Router.router(vertx);
// Store session information on the server side
SessionStore sessionStore = LocalSessionStore.create(vertx);
SessionHandler sessionHandler = SessionHandler.create(sessionStore);
router.route().handler(sessionHandler);
// Expose form parameters in request
router.route().handler(BodyHandler.create());
// CSRF handler setup required for logout form
String csrfSecret = "zwiebelfische";
router.route().handler(CSRFHandler.create(vertx, csrfSecret));
// Used for backend calls with bearer token
WebClient webClient = WebClient.create(vertx);
String hostname = System.getProperty("http.host", "localhost");
int port = Integer.getInteger("http.port", 8090);
String baseUrl = String.format("http://%s:%d", hostname, port);
String oauthCallbackPath = "/callback";
JsonObject keycloakJson = new JsonObject()
.put("realm", "realmissimo") // (1)
.put("auth-server-url", "http://localhost:8080/auth")
.put("ssl-required", "external")
.put("resource", "vertx") // (3)
.put("credentials", new JsonObject().put("secret", "secret-here")); // (4)
OAuth2Auth keycloakProvider = KeycloakAuth.create(vertx, keycloakJson);
if (keycloakProvider == null) throw new RuntimeException("Could not configure Keycloak integration via OpenID Connect Discovery Endpoint. Is Keycloak running?");
OAuth2AuthHandler oauth2 = OAuth2AuthHandler.create(vertx, keycloakProvider, baseUrl + oauthCallbackPath) //
.setupCallback(router.get(oauthCallbackPath));
// protect everything in the protected part
router.route("/protected/*").handler(oauth2);
configureRoutes(router, webClient, keycloakProvider);
getVertx().createHttpServer().requestHandler(router).listen(port);
}
现在,当我尝试访问 /protected/* 下的资源时,它们实际上需要 keycloak 身份验证才能继续。主要问题是我还想对这些路由执行一些基于角色的授权检查,但要么调用已弃用,要么我发现错误:
- 首先尝试:
private void configureRoutes(Router router, WebClient webClient, OAuth2Auth oauth2Auth) {
router.get("/").handler(this::handleIndex);
router.get("/protected/").handler(this::handleGreet);
router.get("/protected/user").handler( h-> this.handleUserPage(h, oauth2Auth));
router.get("/protected/admin").handler(this::handleAdminPage);
....
和 /protected/user 处理程序:
private void handleUserPage(RoutingContext ctx, OAuth2Auth oauth2Auth) {
User user = ctx.user();
if (user == null) {
respondWithServerError(ctx, "text/html", String.format("<h1>Request failed %s</h1>", "user missing"));
return;
}
AuthorizationProvider authz = KeycloakAuthorization.create();
authz.getAuthorizations(user)
.onSuccess(v -> {
if (RoleBasedAuthorization.create("role")
.setResource("realm")
.match(user)) {
// this user is authorized to manage its account
logger.info("match");
}else logger.info("UNmatch");
})
.onFailure( t -> { logger.severe(t.getMessage()); logger.severe(t.toString());});
....
获取 .onFailure 并打印:
io.vertx.core.impl.NoStackTraceThrowable:用户不包含解码的令牌
- 第二次尝试,查看有关使用 vert.x 和 keycloak 的各种官方 vert.x 博客文章,他们建议使用
user.isAuthorized()
但似乎已被弃用。从 3 到 4 的迁移指南指出该方法已移植,但现在在 4.2.3 中已弃用,并且没有提及任何未弃用的替代方法。
有谁知道如何正确检查用户是否具有特定角色或属于给定组?在我的情况下,我有 keycloak 用户名:user1,角色:正常和用户名:user2,角色:admin
最后的考虑:老实说,我对如何使用 vert.x 和 keycloak 实现授权流程感到很困惑。我也非常不鼓励继续学习这项新技术,因为通常很难找到更新和清晰的文档或操作指南或资源(所有官方博客文章都是针对以前的版本,不清楚应该如何弃用的东西被替换,找不到有关如何调试或解决错误的提示)。尽管如此,我还是决心继续学习,因为该框架比 spring-boot 感觉更轻、更快、更酷。提前致谢。