0

我正在尝试为学习目的构建一个简单的 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 身份验证才能继续。主要问题是我还想对这些路由执行一些基于角色的授权检查,但要么调用已弃用,要么我发现错误:

  1. 首先尝试:
 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:用户不包含解码的令牌

  1. 第二次尝试,查看有关使用 vert.x 和 keycloak 的各种官方 vert.x 博客文章,他们建议使用user.isAuthorized() 但似乎已被弃用。从 3 到 4 的迁移指南指出该方法已移植,但现在在 4.2.3 中已弃用,并且没有提及任何未弃用的替代方法。

有谁知道如何正确检查用户是否具有特定角色或属于给定组?在我的情况下,我有 keycloak 用户名:user1,角色:正常和用户名:user2,角色:admin

最后的考虑:老实说,我对如何使用 vert.x 和 keycloak 实现授权流程感到很困惑。我也非常不鼓励继续学习这项新技术,因为通常很难找到更新和清晰的文档或操作指南或资源(所有官方博客文章都是针对以前的版本,不清楚应该如何弃用的东西被替换,找不到有关如何调试或解决错误的提示)。尽管如此,我还是决心继续学习,因为该框架比 spring-boot 感觉更轻、更快、更酷。提前致谢。

4

0 回答 0