Quantcast
Channel: Active questions tagged servlets - Stack Overflow
Viewing all articles
Browse latest Browse all 714

Invalidating old httpsession drops current httpsession's context

$
0
0

My app handles logins with a @ViewScoped LoginBean, which is injected with a @SessionScoped SessionBean that stores user information and the current HttpSession. This app allows a user N separate sessions. After reaching that limit the user can only create another by killing off the oldest. This is done in the same LoginBean by asking the unmanaged UserSessionManager for the oldest SessionBean, and then invalidating its HttpSession.

Thus, logging in with session "A", we invalidate session "B". This all goes according to plan. But then, sometime during the remaining JSF phases, we also lose the SessionBean for session "A". Tracing down into the CDI code it appears that the session context for session "A" is being destroyed so when the redisplay finishes we have all new session beans.

We are using MyFaces 2.3.6, OpenWebBeans 2.0.16, OpenJDK 11

Is this a bug in OWB, or expected bahavior?

I'm also wondering if I have a fundamental misconception. If I save a SessionBean in my UserSessionManager and the retrieve it during a different session, should it retain its original state or does it get re-evaluated in the new SessionScoped context? I've been finding debugging difficult because my objects seem to actually be proxies, and the UI and debugger show different values at times.

Update 4/27/20:The @SessionScoped SessionBean is being destroyed by org.apache.webbeans.web.context.WebContextsService#destroyRequestContext() where it destroys the "PropagatedSessionContext". This PropagatedSessionContext is being set by WebContextsService#destroySessionContext(), which is designating the local session to be destroyed despite being given a different specific session. This is where I'm wondering if it's a bug in OWB.

Here's a simplified example of the code:

(In this test code I've made the SessionManager an @ApplicationScoped bean. In the original code it isn't, but the behavior is the same.)

@Named("loginbean")@ViewScopedpublic class LoginBean implements Serializable {    private static final long serialVersionUID = 1L;    private String username;    @Inject private ExternalContext externalContext;    @Inject private SessionBean session;    @Inject private SessionManager sessionMgr;    public String killOldestDoLogin() {        List<SessionInfo> sessions = sessionMgr.getSessions();        SessionInfo oldest = sessions.get(0);        sessionMgr.killSession(oldest.getSessionId());        return doLogin();    }    public String doLogin() {        username = username.trim();        if (username != null && username.length() > 0) {            // After a successful login, avoid session fixation attacks by            // rotating the session ID.  This isn't strictly necessary as Faces has            // its own session ID that a third party wouldn't have access to            if (externalContext != null) {                HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();                if (request != null && request.isRequestedSessionIdValid()) {                    newSessionId   = request.changeSessionId();                                    }            }                        HttpSession http = (HttpSession)externalContext.getSession(false);            session.setUsername(username);            session.setHttpSession(http);            sessionMgr.addSession(http, session);                    }         return "startPage.jsf");    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }}

.

@Named("sessionbean")@SessionScopedpublic class SessionBean implements Serializable {    private static final long serialVersionUID = 1L;    private String username;    private HttpSession httpSession;    public void reset() {        username = null;        httpSession = null;    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public HttpSession getHttpSession() {        return httpSession;    }    public void setHttpSession(HttpSession session) {        this.httpSession = session;    }    public String getSessionId() {        return httpSession == null ? "null" : this.httpSession.getId();    }}

.

@Named("sessionmanager")@ApplicationScopedpublic class SessionManager {    private HashMap<String,HttpSession> sessionMap = new HashMap<>();    private HashMap<String,SessionBean> beanMap    = new HashMap<>();    public void addSession(HttpSession http, SessionBean bean) {        beanMap.put(http.getId(),  bean);        sessionMap.put(http.getId(), http);    }    public boolean killSession(String sessionId) {        HttpSession session = sessionMap.get(sessionId);        sessionMap.remove(sessionId);        beanMap.remove(sessionId);        if (session != null) {            session.invalidate();        }        return session != null;    }    public List<SessionInfo> getSessions() {        List<SessionInfo> result = new ArrayList<>();        for (String sessionId : sessionMap.keySet()) {            SessionBean bean = beanMap.get(sessionId);            HttpSession http = sessionMap.get(sessionId);            SessionInfo info = new SessionInfo();            info.setUsername(bean.getUsername());            info.setSessionId(sessionId);            info.setHttpSession(http));            result.add(info);        }        return result;    }}

.

public class SessionInfo {    private String      username;    private String      sessionId;    private HttpSession httpSession;    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public String getSessionId() {        return sessionId;    }    public void setSessionId(String sessionId) {        this.sessionId = sessionId;    }    public HttpSession getHttpSession() {        return httpSession;    }    public void setHttpSession(HttpSession httpSession) {        this.httpSession = httpSession;    }}

Viewing all articles
Browse latest Browse all 714

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>