8 Replies Latest reply on Feb 20, 2015 9:11 AM by skull

    http Session

    skull

      How i can access all session in a wildlfy cluster?

      i try httpsessionlistener, but when in a domain the session is shared in infinispan then de lister do not trigger in all node from cluster. And some session are created in other nodes.

        • 1. Re: http Session
          pferraro

          HttpSessionListener events are local only (as dictated by the servlet specification).  However, there is nothing preventing you from broadcasting this information to other nodes in the cluster using the WildFly clustering API.

          e.g.

          @WebListener
          public class MyContextListener implements ServletContextListener {
              @Resource(lookup = "java:jboss/clustering/dispatcher/web")
              private CommandDispatcherFactory<ServletContext> factory;
          
              @Override
              public void contextInitialized(ServletContextEvent event) {
                  ServletContext context = event.getServletContext();
                  CommandDispatcher<ServletContext> dispatcher = this.factory.createCommandDispatcher("my-dispatcher", context);
                  event.getServletContext().setAttribute("dispatcher", dispatcher);
              }
          
              @Override
              public void contextDestroyed(ServletContextEvent event) {
                  ServletContext context = event.getServletContext();
                  CommandDispatcher<ServletContext> dispatcher = (CommandDispatcher<ServletContext>) context.getAttribute("dispatcher");
                  dispatcher.close();
                  context.removeAttribute("dispatcher");
              }
          }
          
          @WebListener
          public void MySessionListener implements HttpSessionListener {
              @Override
              public void sessionCreated(HttpSessionEvent event) {
                  HttpSession session = event.getSession();
                  CommandDispatcher<ServletContext> dispatcher = (CommandDispatcher<ServletContext>) session.getServletContext().getAttribute("dispatcher");        
                  Map<Node, CommandResponse<Void>> responses = dispatcher.executeOnCluster(new SessionCreatedCommand(session.getId());
              }
              
              @Override
              public void sessionDestroyed(HttpSessionEvent event) {
              }
          }
          
          public void SessionCreatedCommand implements Command<Void, ServletContext> {
              private final String sessionId;
          
              public SessionCreatedCommand(String sessionId) {
                  this.sessionId = sessionId;
              }
          
              @Override
              public Void execute(ServletContext context) {
                  // Do whatever
              }
          }
          
          
          
          
          
          

           

          Just keep in mind that the attributes of your command object must be serializable.

          1 of 1 people found this helpful
          • 2. Re: http Session
            skull

            I downloaded the sources of wildfly found the ServletContextImp class and with reflection will access the sessions getSession(sessionId) and getActiveSessions() (Deployment)

            after that will try your "broadcast"

            i was doing that with JMS but too much request because the lastAcessTime from HttpSession

             

             

            Can i access a some user sessionId to remove or invalidate it? keep in mind that is not the sessionId from currrent request, is the old session from some user.

            • 3. Re: http Session
              skull

              After a long search, and go deep in to jboss/wildlfy source code (sources from Paul Ferraro). i got a conclusion: just can access another session by id and edit it with some reflections:

               

               

                HttpSessionImpl session;
              
                Field field = SystemUtil.getDeclaredField("deployment", servletContext.getClass(), false);
                Deployment deployment;
                try {
                     field.setAccessible(true);
                     deployment = (Deployment) field.get(servletContext);
                     SessionManager undertowSession = (SessionManager) deployment.getSessionManager();
              
                     Field batchManager = SystemUtil.getDeclaredField("manager", undertowSession.getClass(), false);
                     batchManager.setAccessible(true);
                     org.wildfly.clustering.web.session.SessionManager<?> managerCluster = (org.wildfly.clustering.web.session.SessionManager<?>) batchManager.get(undertowSession);
              
                     Method method = managerCluster.getClass().getMethod("getBatcher", new Class[0]);
                     Batcher result = (Batcher) method.invoke(managerCluster, new Object[0]);
              
                     Method methodStart = result.getClass().getMethod("startBatch", new Class[0]);
                     Batch batch = (Batch) methodStart.invoke(result, new Object[0]);
                     try {
                          Method methodFind = managerCluster.getClass().getMethod("findSession", String.class);
                          @SuppressWarnings("unchecked")
                          Session<LocalSessionContext> session1 = (Session<LocalSessionContext>) methodFind.invoke(managerCluster, sessionId);
                          if (session == null) {
                               batch.close();
                               return null;
                          }
                          DistributableSession distributableSession = new DistributableSession((UndertowSessionManager) undertowSession, session1, servletContext.getSessionConfig(), batch);
                          return HttpSessionImpl.forSession(distributableSession, servletContext, false);
                     } catch (RuntimeException | Error e) {
                          batch.discard();
                          throw e;
                     }
                } catch (IllegalArgumentException | IllegalAccessException | NoSuchMethodException | SecurityException | InvocationTargetException e) {
                     e.printStackTrace();
                }
              
              • 4. Re: http Session
                pferraro

                Can I ask what exactly you are trying to achieve?  The ability to access any session by its session identifier was revoked in Servlet 2.1 because of the obvious security issues.  http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSessionContext.html

                • 5. Re: http Session
                  pferraro

                  I strongly recommend against doing this.  The association between (and names of) internal objects/attributes may change abruptly between releases without notice.

                  • 6. Re: http Session
                    skull

                    Of course. I try to do not accept that same user login in multiples platforms without logout him from another.

                    Then i was using the HttpSessionLister to keep a singleton with session then i locate the session and invalidate it. But when i go to cluster i cannot have a singleton for all clusters, then i try to access the session and when found that user i invalidate the session.

                     

                    Did you have some another idea that i can send that code to trash and use some really useful?

                    • 7. Re: http Session
                      pferraro

                      I think I understand your use case now.  How do you currently handle authentication?  Are you using container managed authentication?

                      In general, it's not a good idea to hold references to the HttpSession.  I'm also skeptical as to whether your strategy above can handle concurrent access to different applications from the same "user", which I would imagine you would want to prevent.

                      Unless I'm making some erroneous assumptions, I think want you really need here are shared sessions across your applications.  To do this, following authentication, you would store some application identifier, which unique identifies the application to which the user is currently "logged in", in a session attribute.  You can then write a servlet filter, or similar, that validates whether or not the application identifier matches the current application, if a request arrives for an existing session, and if not, invalidating the session, forcing the user to reauthenticate.  This way a session is only ever invalidated by the owning request.

                      http://www.mastertheboss.com/jboss-server/wildfly-8/sharing-httpsession-between-web-applications-in-an-ear

                      • 8. Re: http Session
                        skull

                        i am using jaas and using the request.login to authenticate, my LoginModule do everything about checks.

                        for the session, i use it to handle all user that is online, your last access (session.getLastAccessedTime()), when login (session.getCreationTime()) and a manager to kill session (administrator feature)

                        with the websocket session i merge some info with httpsession to send a messages for users.

                         

                        But like you sad if i can recover authentication from a specific user to force logout him will be cool and can view all users. Session is usefull because when logout it disapear from the list.