How to change JSESSIONID after login in Vaadin8?

不羁岁月 提交于 2020-08-10 19:12:33

问题


I'm trying to implement session reinitialization for Vaadin for security reasons (Session_fixation) but failing to do so.

I am using Vaadin 8.9.4 with @Push and WildFly 8.1.0.Final. Also using the Vaadin heartbeat and @PreserveOnRefresh annotation.

I have tried using the VaadinService.reinitializeSession but with no luck. App just hangs, refresh will throw me back to login screen (with new JSESSSIONID though).

Here's an example what I have tried: VaadinService.reinitializeSession(VaadinService.getCurrentRequest()); from which I'm getting the following error:

16:23:35,520 WARNING [com.vaadin.server.communication.PushHandler] (default task-41) Error while ending request: java.lang.IllegalStateException: UT000010: Session not found mGoJr6uWAgVH3yCuW5zq_-sg
at io.undertow.server.session.InMemorySessionManager$SessionImpl.getMaxInactiveInterval(InMemorySessionManager.java:310) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.servlet.spec.HttpSessionImpl.getMaxInactiveInterval(HttpSessionImpl.java:108) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
at com.vaadin.server.WrappedHttpSession.getMaxInactiveInterval(WrappedHttpSession.java:49) [vaadin-server-8.9.4.jar:8.9.4]
at com.vaadin.server.VaadinService.getUidlRequestTimeout(VaadinService.java:1344) [vaadin-server-8.9.4.jar:8.9.4]
at com.vaadin.server.VaadinService.isSessionActive(VaadinService.java:1406) [vaadin-server-8.9.4.jar:8.9.4]
at com.vaadin.server.VaadinService.cleanupSession(VaadinService.java:1236) [vaadin-server-8.9.4.jar:8.9.4]
at com.vaadin.server.VaadinService.requestEnd(VaadinService.java:1451) [vaadin-server-8.9.4.jar:8.9.4]
at com.vaadin.server.communication.PushHandler.callWithUi(PushHandler.java:285) [vaadin-server-8.9.4.jar:8.9.4]
at com.vaadin.server.communication.PushHandler.onMessage(PushHandler.java:534) [vaadin-server-8.9.4.jar:8.9.4]
at com.vaadin.server.communication.PushAtmosphereHandler.onMessage(PushAtmosphereHandler.java:87) [vaadin-server-8.9.4.jar:8.9.4]
at com.vaadin.server.communication.PushAtmosphereHandler.onRequest(PushAtmosphereHandler.java:77) [vaadin-server-8.9.4.jar:8.9.4]
at org.atmosphere.cpr.AsynchronousProcessor.action(AsynchronousProcessor.java:225) [atmosphere-runtime-2.4.30.vaadin1.jar:2.4.30.vaadin1]
at org.atmosphere.cpr.AsynchronousProcessor.suspended(AsynchronousProcessor.java:114) [atmosphere-runtime-2.4.30.vaadin1.jar:2.4.30.vaadin1]
at org.atmosphere.container.Servlet30CometSupport.service(Servlet30CometSupport.java:67) [atmosphere-runtime-2.4.30.vaadin1.jar:2.4.30.vaadin1]
at org.atmosphere.cpr.AtmosphereFramework.doCometSupport(AtmosphereFramework.java:2297) [atmosphere-runtime-2.4.30.vaadin1.jar:2.4.30.vaadin1]
at org.atmosphere.websocket.DefaultWebSocketProcessor.dispatch(DefaultWebSocketProcessor.java:594) [atmosphere-runtime-2.4.30.vaadin1.jar:2.4.30.vaadin1]
at org.atmosphere.websocket.DefaultWebSocketProcessor$3.run(DefaultWebSocketProcessor.java:345) [atmosphere-runtime-2.4.30.vaadin1.jar:2.4.30.vaadin1]
at org.atmosphere.util.VoidExecutorService.execute(VoidExecutorService.java:101) [atmosphere-runtime-2.4.30.vaadin1.jar:2.4.30.vaadin1]
at org.atmosphere.websocket.DefaultWebSocketProcessor.dispatch(DefaultWebSocketProcessor.java:340) [atmosphere-runtime-2.4.30.vaadin1.jar:2.4.30.vaadin1]
at org.atmosphere.websocket.DefaultWebSocketProcessor.invokeWebSocketProtocol(DefaultWebSocketProcessor.java:448) [atmosphere-runtime-2.4.30.vaadin1.jar:2.4.30.vaadin1]
at org.atmosphere.container.JSR356Endpoint$3.onMessage(JSR356Endpoint.java:272) [atmosphere-runtime-2.4.30.vaadin1.jar:2.4.30.vaadin1]
at org.atmosphere.container.JSR356Endpoint$3.onMessage(JSR356Endpoint.java:269) [atmosphere-runtime-2.4.30.vaadin1.jar:2.4.30.vaadin1]
at io.undertow.websockets.jsr.FrameHandler$7.run(FrameHandler.java:257) [undertow-websockets-jsr-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.websockets.jsr.ServerWebSocketContainer$1.run(ServerWebSocketContainer.java:303) [undertow-websockets-jsr-1.0.15.Final.jar:1.0.15.Final]
at io.undertow.websockets.jsr.OrderedExecutor$ExecutorTask.run(OrderedExecutor.java:49) [undertow-websockets-jsr-1.0.15.Final.jar:1.0.15.Final]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [rt.jar:1.8.0_242]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [rt.jar:1.8.0_242]
at java.lang.Thread.run(Thread.java:748) [rt.jar:1.8.0_242]

The error is thrown when Vaadin is trying to "Restores all attributes (security key, reference to this context instance) with newSession.setAttribute(name, value); (VaadinService.java:1150 onwards)

Is this Vaadin problem or WildFly problem and how to solve it?

EDIT: I noticed that if I reinitialize the sessionID in UI.init() the sessionID will get changed and updated on browser but of course user has not logged in yet. When I try to reinitialize anywhere else, it will change the server side sessionID but not on browser. My login screen is a custom component instantiated on UI.init().

EDIT 31.7.2020 (making progress?)

I started experimenting again by using @Push with LONG_POLLING mode and I might be making some progress but still facing an issues.

After login I'm issuing the VaadinService.reinitializeSession and the server side sessionId is getting changed and I'm not getting any errors on log. Client side sessionId is not changed and after ~15s I get "Communication problem" from app and the sessionId on client gets changed to completely new one (not any that server has had). Also, Chrome console show that hearbeat is getting "404 (Not Found)" as soon as reinitializeSession has been called. After 5 or so 404 errors console shows this:

[Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.

And it's about exactly the same behaviour with using @Push with WEBSOCKET_XHR.

I have tried this using also Wildfly 20.0.1 - it's the same with that too.


回答1:


The problem you have is probably due use of WebSocket with Push. There are some workarounds which are discussed in detail in blog post on Vaadin site.

The post says

  1. You can use the WEBSOCKET_XHR transport instead of Websocket.

  2. Disable push completely in the login page (i.e. don’t put @Push on your UI) and programmatically enable it after the user has logged on.

  3. Use a push mechanism that uses basic HTTP, i.e. transport mode LONG_POLLING.

The further investigation revealed, that the info is a bit outdated, since Chrome from version 80 onwards removed support of synchronous XHR during page dismissal.

This narrows the working option actually to combination of 1. and 2. The Push needs to be disabled during re-initialization, i.e.

public static void sessionFixation() {
    // Chrome 80 does not support synchronous XHR during page dismissal anymore
    // thus Push needs to be disabled during session re-initialization
    UI.getCurrent().getPushConfiguration().setPushMode(PushMode.DISABLED);
    VaadinService.reinitializeSession(VaadinService.getCurrentRequest());
    UI.getCurrent().getPushConfiguration().setPushMode(PushMode.AUTOMATIC);
}

There is a fully functioning demo app in https://github.com/TatuLund/cdi-demo

PS. Just to point out, the latest Vaadin version as writing of this answer is 8.11.1, I recommend to upgrade. Also Wildfly 8 is quite old.



来源:https://stackoverflow.com/questions/63035590/how-to-change-jsessionid-after-login-in-vaadin8

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!