简体   繁体   English

登录 Vaadin8 后如何更改 JSESSIONID?

[英]How to change JSESSIONID after login in Vaadin8?

I'm trying to implement session reinitialization for Vaadin for security reasons ( Session_fixation ) but failing to do so.出于安全原因( Session_fixation ),我正在尝试为 Vaadin 实施 session 重新初始化,但没有这样做。

I am using Vaadin 8.9.4 with @Push and WildFly 8.1.0.Final.我正在使用带有@Push和 WildFly 8.1.0.Final 的 Vaadin 8.9.4。 Also using the Vaadin heartbeat and @PreserveOnRefresh annotation.还使用 Vaadin 心跳和 @PreserveOnRefresh 注释。

I have tried using the VaadinService.reinitializeSession but with no luck.我试过使用VaadinService.reinitializeSession但没有运气。 App just hangs, refresh will throw me back to login screen (with new JSESSSIONID though).应用程序只是挂起,刷新会让我回到登录屏幕(尽管使用新的 JSESSSIONID)。

Here's an example what I have tried: VaadinService.reinitializeSession(VaadinService.getCurrentRequest());这是我尝试过的一个示例: 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 )当 Vaadin 尝试“使用newSession.setAttribute(name, value);VaadinService.java:1150 起)时抛出错误

Is this Vaadin problem or WildFly problem and how to solve it?这是 Vaadin 问题还是 WildFly 问题以及如何解决?

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.编辑:我注意到,如果我在UI.init()中重新初始化 sessionID,则 sessionID 将在浏览器上更改和更新,但当然用户尚未登录。 When I try to reinitialize anywhere else, it will change the server side sessionID but not on browser.当我尝试在其他任何地方重新初始化时,它会更改服务器端 sessionID 但不会在浏览器上。 My login screen is a custom component instantiated on UI.init().我的登录屏幕是在 UI.init() 上实例化的自定义组件。

EDIT 31.7.2020 (making progress?)编辑 31.7.2020(取得进展?)

I started experimenting again by using @Push with LONG_POLLING mode and I might be making some progress but still facing an issues.我通过使用带有 LONG_POLLING 模式的 @Push 再次开始试验,我可能取得了一些进展,但仍然面临问题。

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.登录后,我发出VaadinService.reinitializeSession并且服务器端 sessionId 正在更改,并且我没有在日志中收到任何错误。 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).客户端 sessionId 没有更改,大约 15 秒后,我从应用程序收到“通信问题”,客户端上的 sessionId 更改为全新的(不是服务器拥有的)。 Also, Chrome console show that hearbeat is getting "404 (Not Found)" as soon as reinitializeSession has been called.此外,Chrome 控制台显示,一旦调用 reinitializeSession,heartbeat 就会得到“404(未找到)”。 After 5 or so 404 errors console shows this:在 5 个左右 404 错误控制台后显示:

[Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. [弃用] 主线程上的同步 XMLHttpRequest 已弃用,因为它对最终用户的体验产生不利影响。 For more help, check https://xhr.spec.whatwg.org/.如需更多帮助,请查看https://xhr.spec.whatwg.org/。

And it's about exactly the same behaviour with using @Push with WEBSOCKET_XHR.这与使用 @Push 和 WEBSOCKET_XHR 的行为完全相同。

I have tried this using also Wildfly 20.0.1 - it's the same with that too.我也尝试过使用 Wildfly 20.0.1 - 它也一样。

The problem you have is probably due use of WebSocket with Push.您遇到的问题可能是由于使用了带有 Push 的 WebSocket。 There are some workarounds which are discussed in detail in blog post on Vaadin site. Vaadin 网站上的博客文章中详细讨论了一些解决方法。

The post says帖子说

  1. You can use the WEBSOCKET_XHR transport instead of Websocket.您可以使用 WEBSOCKET_XHR 传输而不是 Websocket。

  2. Disable push completely in the login page (ie don't put @Push on your UI) and programmatically enable it after the user has logged on.在登录页面中完全禁用推送(即不要将@Push 放在您的用户界面上)并在用户登录后以编程方式启用它。

  3. Use a push mechanism that uses basic HTTP, ie transport mode LONG_POLLING.使用使用基本 HTTP 的推送机制,即传输模式 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.进一步调查显示,该信息有点过时,因为 Chrome 从版本 80 开始在页面关闭期间删除了对同步 XHR 的支持。

This narrows the working option actually to combination of 1. and 2. The Push needs to be disabled during re-initialization, ie这实际上将工作选项缩小到 1. 和 2 的组合。在重新初始化期间需要禁用推送,即

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 https://github.com/TatuLund/cdi-demo中有一个功能齐全的演示应用程序

PS. PS。 Just to point out, the latest Vaadin version as writing of this answer is 8.11.1, I recommend to upgrade.需要指出的是,撰写此答案的最新 Vaadin 版本是 8.11.1,我建议升级。 Also Wildfly 8 is quite old. Wildfly 8 也很老了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM