我们正在尝试将Keycloak与我们的Vert.x + Angular Web应用集成。我们希望保护所有应用程序的安全,并在/出现时直接重定向到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接口连接并转发至:
我们收到此错误:
内部服务器错误
堆栈跟踪:
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 googlegroup中发布了此问题:https://groups.google.com/forum/#!topic/vertx/ms3ylVWC8tc
答案 0 :(得分:2)
解决方案是将BodyHandler
放在其他所有路由声明之前(感谢Vert.x邮件列表中的Thomas Segismont)。
有关更多详细信息,请参见:https://groups.google.com/forum/#!topic/vertx/ms3ylVWC8tc