登录 Vaadin8 后如何更改 JSESSIONID? [英] How to change JSESSIONID after login in Vaadin8?

查看:110
本文介绍了登录 Vaadin8 后如何更改 JSESSIONID?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出于安全原因,我正在尝试为 Vaadin 实施会话重新初始化 (Session_fixation) 但没有这样做.

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

我正在使用 Vaadin 8.9.4 和 @Push 和 WildFly 8.1.0.Final.还使用 Vaadin 心跳和 @PreserveOnRefresh 注释.

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

我曾尝试使用 VaadinService.reinitializeSession 但没有成功.应用程序只是挂起,刷新会让我回到登录屏幕(尽管使用了新的 JSESSSIONID).

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).

这是我尝试过的示例:VaadinService.reinitializeSession(VaadinService.getCurrentRequest());,从中我收到以下错误:

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]

当 Vaadin 尝试恢复所有属性(安全密钥,对此上下文实例的引用)"时抛出错误newSession.setAttribute(name, value); (VaadinService.java:1150 起)

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 问题还是 WildFly 问题以及如何解决?

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

我注意到,如果我在 UI.init() 中重新初始化 sessionID,则 sessionID 将在浏览器上更改和更新,但当然用户尚未登录然而.当我尝试在其他任何地方重新初始化时,它会更改服务器端 sessionID,但不会更改浏览器.我的登录屏幕是在 UI.init() 上实例化的自定义组件.

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(取得进展?)

我通过在 LONG_POLLING 模式下使用 @Push 再次开始试验,我可能取得了一些进展,但仍然面临问题.

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

登录后,我发出 VaadinService.reinitializeSession 并且服务器端 sessionId 正在更改,并且我没有收到任何日志错误.客户端 sessionId 未更改,大约 15 秒后出现通信问题";从应用程序和客户端上的 sessionId 更改为全新的(不是该服务器拥有的任何一个).此外,Chrome 控制台显示 heartbeat 出现404(未找到)".一旦调用了 reinitializeSession.大约 5 个 404 错误后,控制台显示:

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:

[弃用] 主线程上的同步 XMLHttpRequest 已弃用,因为它会对最终用户的体验产生不利影响.如需更多帮助,请查看 https://xhr.spec.whatwg.org/.

这与在 WEBSOCKET_XHR 中使用 @Push 的行为完全相同.

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

我也使用 Wildfly 20.0.1 尝试过这个 - 它也是一样的.

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

推荐答案

您遇到的问题可能是将 WebSocket 与 Push 结合使用.中详细讨论了一些解决方法Vaadin 网站上的博文.

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.

帖子说

  1. 您可以使用 WEBSOCKET_XHR 传输代替 Websocket.

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

在登录页面中完全禁用推送(即不要在您的 UI 上放置 @Push)并在用户登录后以编程方式启用它.

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.

使用使用基本 HTTP 的推送机制,即传输模式 LONG_POLLING.

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

进一步调查显示,该信息有点过时,因为 Chrome 从 80 版开始在页面关闭期间取消了对同步 XHR 的支持.

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.

这实际上将工作选项缩小到 1. 和 2 的组合.在重新初始化期间需要禁用推送,即

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);
}

https://github.com/TatuLund/cdi-demo 中有一个功能齐全的演示应用程序

附注.只是指出,写这个答案的最新 Vaadin 版本是 8.11.1,我建议升级.Wildfly 8 也很老了.

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.

这篇关于登录 Vaadin8 后如何更改 JSESSIONID?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆