Keycloak + Vert.x java.lang.IllegalStateException: запрос уже прочитан - PullRequest
0 голосов
/ 24 октября 2018

Мы пытаемся интегрировать Keycloak с нашим веб-приложением Vert.x + Angular.Мы хотим защитить все приложение и напрямую перенаправить на страницу входа в Keycloak при входе / Вот наша конфигурация:

@Override
public void start() {
   var router = Router.router(vertx);

   OAuth2Auth oAuth2Auth = KeycloakAuth.create(vertx, OAuth2FlowType.AUTH_CODE, new JsonObject("{\n" +
         "  \"realm\": \"master\",\n" +
         "  \"auth-server-url\": \"http://localhost:32804/auth\",\n" +
         "  \"ssl-required\": \"external\",\n" +
         "  \"resource\": \"RA\",\n" +
         "  \"credentials\": {\n" +
         "    \"secret\": \"06cb4f6c-ccc4-4391-8529-8a2f1a96a10d\"\n" +
         "  },\n" +
         "  \"confidential-port\": 0\n" +
         "}"));
   OAuth2AuthHandler authHandler = OAuth2AuthHandler.create(oAuth2Auth, "http://localhost:9000")
         .setupCallback(router.route("/callback"));
   router.route("/*").handler(authHandler);

   router.route().handler(BodyHandler.create());
   router.route().handler(StaticHandler.create());
   router.route().handler(LoggerHandler.create(LoggerFormat.DEFAULT));

   router.route(HttpMethod.POST, "/api/encounter/create").handler(this::encounterCreationHandler);
   router.route(HttpMethod.POST, "/api/encounter/:id/mark-as-seen").handler(this::encounterToggleMarkAsReadHandler);
   router.route(HttpMethod.GET, "/api/encounters").handler(this::getActiveEncountersHandler);
   router.route(HttpMethod.GET, "/api/encounter/:id").handler(this::encounterByIdHandler);
   router.route(HttpMethod.GET, "/api/services").handler(this::getServicesHandler);
   router.route("/*").handler(this::defaultHandler);

   vertx.createHttpServer()
         .requestHandler(router::accept)
         .listen(config().getInteger("server.port", 9000));
}

private void defaultHandler(RoutingContext rc) {
   rc.response().sendFile("webroot/index.html");
}

Все работает нормально, пока мы не подключены через интерфейс Keycloak и не перенаправлены на:

http://localhost:9000/callback?state=%2F&session_state=096cc2bc-5648-466c-85a3-ae12789a7648&code=eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..6FzWoSHHdE51s_0uIhTwqA.KSEtJEbOU464u74Z9qTkKx563ErjoDjtOB6G5EMlFQvrFoQGGc0RSJ57S333vNbGbJd1hEH0wRHwdL5Slty3V4K_VAqVEpyfeVCSdZDu8Jo210Ev0h5k_yyDH_g7HABkWkJFquWoM2p-_Pw94oD9rFq7No0dxuIT08MyzcTBMylPogq52YMfgER57mSvTL5p6VxsGSfc-4ouPWxebets5DHBAKw3RZwFKcVq-KyJ4bncAR_ZjqyybjSjftKfP_DI.ANjNUh9-QlnldFM0I_B-GA

мы получаем эту ошибку:

Внутренняя ошибка сервера

Трассировка стека:

java.lang.IllegalStateException: Request has already been read
    at io.vertx.core.http.impl.HttpServerRequestImpl.checkEnded(HttpServerRequestImpl.java:438) ~[vertx-core-3.5.4.jar:3.5.4]
    at io.vertx.core.http.impl.HttpServerRequestImpl.handler(HttpServerRequestImpl.java:203) ~[vertx-core-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.impl.HttpServerRequestWrapper.handler(HttpServerRequestWrapper.java:39) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.handler.impl.BodyHandlerImpl.handle(BodyHandlerImpl.java:73) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.handler.impl.BodyHandlerImpl.handle(BodyHandlerImpl.java:42) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.reactivex.ext.web.handler.BodyHandler.handle(BodyHandler.java:74) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.reactivex.ext.web.handler.BodyHandler.handle(BodyHandler.java:37) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.reactivex.ext.web.Route$1.handle(Route.java:155) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.reactivex.ext.web.Route$1.handle(Route.java:153) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:225) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:120) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:133) [vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.handler.impl.AuthHandlerImpl.lambda$authorizeUser$3(AuthHandlerImpl.java:219) [vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.handler.impl.AuthHandlerImpl.authorize(AuthHandlerImpl.java:107) [vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.handler.impl.AuthHandlerImpl.authorizeUser(AuthHandlerImpl.java:213) [vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.handler.impl.AuthHandlerImpl.handle(AuthHandlerImpl.java:125) [vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.handler.impl.AuthHandlerImpl.handle(AuthHandlerImpl.java:39) [vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.reactivex.ext.web.handler.OAuth2AuthHandler.handle(OAuth2AuthHandler.java:78) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.reactivex.ext.web.handler.OAuth2AuthHandler.handle(OAuth2AuthHandler.java:41) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.reactivex.ext.web.Route$1.handle(Route.java:155) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.reactivex.ext.web.Route$1.handle(Route.java:153) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:225) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:120) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:133) [vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.impl.RoutingContextImplBase.restart(RoutingContextImplBase.java:76) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.impl.RoutingContextImpl.reroute(RoutingContextImpl.java:380) [vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.RoutingContext.reroute(RoutingContext.java:404) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.web.handler.impl.OAuth2AuthHandlerImpl.lambda$null$2(OAuth2AuthHandlerImpl.java:220) ~[vertx-web-3.5.4.jar:3.5.4]
    at io.vertx.ext.auth.oauth2.impl.OAuth2AuthProviderImpl.lambda$authenticate$1(OAuth2AuthProviderImpl.java:188) ~[vertx-auth-oauth2-3.5.4.jar:3.5.4]
    at io.vertx.ext.auth.oauth2.impl.flow.AuthCodeImpl.lambda$getToken$0(AuthCodeImpl.java:87) ~[vertx-auth-oauth2-3.5.4.jar:3.5.4]
    at io.vertx.ext.auth.oauth2.impl.flow.AbstractOAuth2Flow.lambda$getToken$0(AbstractOAuth2Flow.java:135) ~[vertx-auth-oauth2-3.5.4.jar:3.5.4]
    at io.vertx.ext.auth.oauth2.impl.OAuth2API.lambda$null$1(OAuth2API.java:121) ~[vertx-auth-oauth2-3.5.4.jar:3.5.4]
    at io.vertx.core.http.impl.HttpClientResponseImpl$BodyHandler.notifyHandler(HttpClientResponseImpl.java:299) ~[vertx-core-3.5.4.jar:3.5.4]
    at io.vertx.core.http.impl.HttpClientResponseImpl.lambda$bodyHandler$0(HttpClientResponseImpl.java:189) ~[vertx-core-3.5.4.jar:3.5.4]
    at io.vertx.core.http.impl.HttpClientResponseImpl.handleEnd(HttpClientResponseImpl.java:253) ~[vertx-core-3.5.4.jar:3.5.4]
    at io.vertx.core.http.impl.Http1xClientConnection$StreamImpl.endResponse(Http1xClientConnection.java:424) ~[vertx-core-3.5.4.jar:3.5.4]
    at io.vertx.core.http.impl.Http1xClientConnection.handleResponseEnd(Http1xClientConnection.java:507) ~[vertx-core-3.5.4.jar:3.5.4]
    at io.vertx.core.http.impl.Http1xClientHandler.handleMessage(Http1xClientHandler.java:119) ~[vertx-core-3.5.4.jar:3.5.4]
    at io.vertx.core.http.impl.Http1xClientHandler.handleMessage(Http1xClientHandler.java:33) ~[vertx-core-3.5.4.jar:3.5.4]
    at io.vertx.core.net.impl.VertxHandler.lambda$channelRead$1(VertxHandler.java:146) ~[vertx-core-3.5.4.jar:3.5.4]
    at io.vertx.core.impl.ContextImpl.lambda$wrapTask$2(ContextImpl.java:337) ~[vertx-core-3.5.4.jar:3.5.4]
    at io.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:195) ~[vertx-core-3.5.4.jar:3.5.4]
    at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:144) ~[vertx-core-3.5.4.jar:3.5.4]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.19.Final.jar:4.1.19.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.19.Final.jar:4.1.19.Final]

Мы также пытались защитить все, кроме / callback:

router.route("/*").pathRegex("\\/(?!callback).*").handler(authHandler);

, но всегда с одной и той же ошибкой.

Любая помощь или рекомендация, пожалуйста?Даже о том, как правильно защитить все приложения (спереди + сзади) без пользовательской страницы входа (напрямую перенаправить на страницу входа в keycloak).

Заранее спасибо.

PS: Мы опубликовали этовопрос в гуглгруппе Vert.x: https://groups.google.com/forum/#!topic/vertx/ms3ylVWC8tc

1 Ответ

0 голосов
/ 24 октября 2018

Решение состоит в том, чтобы поставить BodyHandler перед каждой другой декларацией маршрута (спасибо Томасу Сегисмонту в списке рассылки Vert.x).

Для получения более подробной информации см. https://groups.google.com/forum/#!topic/vertx/ms3ylVWC8tc

...