TL; DR我们@SessionScoped注入了具有另一个会话内容的bean实例
最近我们遇到了两个客户系统的严重问题.我们的客户在具有WELD 2.0.5的Glassfish 4.0服务器的两台机器上运行相同JSF 2.2应用程序的两个独立实例(因内存泄漏而欢呼!).
一些用户一直在报告问题,例如在提交表单后,响应显示的用户名与最初登录的用户名不同.由于我们无法在开发和测试环境中重现此行为,因此我们开始从生产中获取日志数据系统.
我们记录了什么?
在我们第一次尝试时,我们开始记录哪个用户在某个时间从哪个客户进行了哪个操作.爬过日志后,我们发现了如下序列:
Time Client User Action
.............................
t=0 ClientA UserA Login
t=1 ClientA UserA Logoff
t=2 ClientB UserB Login
t=3 ClientB UserB ActionA
t=4 ClientB *UserA* ActionB
t=5 ClientB UserB Logoff
Run Code Online (Sandbox Code Playgroud)
User A在更换发生之前,替换用户(此处)的会话并不总是结束(有时会导致一个用户注销另一个用户......).那么当前登录的用户存储在哪里?我们将它作为属性存储在@SessionScopedbean中,@RequestScoped只要我们需要这些信息,就会将其存入bean中.这导致我们认为@SessionScoped豆类有时会混淆的理论.
@Named
@javax.enterprise.context.SessionScoped
public class SessionStateBean {
private User user;
public void setUser(...) { }
public User getUser() { }
}
Run Code Online (Sandbox Code Playgroud)
因此,在第二次尝试时,我们通过以下功能扩展了日志数据:
@SessionScopedbean 的值进行比较.@SessionScopedbean的每个实例都接收到自己的UUID,并在构造和销毁bean以及更改用户属性时记录.我们知道@SessionScopedbean有可能有多个代理,被钝化等等,但我们试了一下.关于第一个日志功能,我们开始看到序列显示来自会话范围bean的用户名与存储在HTTP会话中的值之间的实际差异: …