Fix issues with multi session
authorMathieu Baudier <mbaudier@argeo.org>
Thu, 24 Mar 2011 16:38:56 +0000 (16:38 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Thu, 24 Mar 2011 16:38:56 +0000 (16:38 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@4366 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

security/plugins/org.argeo.security.equinox/src/main/java/org/argeo/security/equinox/SpringLoginModule.java
security/plugins/org.argeo.security.ui.rap/plugin.xml
security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureActionBarAdvisor.java
security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureEntryPoint.java
security/plugins/org.argeo.security.ui.rap/src/main/java/org/argeo/security/ui/rap/SecureRapActivator.java
security/plugins/org.argeo.security.ui/src/main/java/org/argeo/security/ui/dialogs/DefaultLoginDialog.java

index 298323b3d345d3fc797df404e7eddcd60b77f036..0e5984532099720cbc627f0be865bb13898a259a 100644 (file)
@@ -1,7 +1,6 @@
 package org.argeo.security.equinox;
 
 import java.util.Map;
-import java.util.Set;
 
 import javax.security.auth.Subject;
 import javax.security.auth.callback.Callback;
@@ -44,10 +43,11 @@ public class SpringLoginModule extends SecurityContextLoginModule {
 
        public boolean login() throws LoginException {
                // try to retrieve Authentication from Subject
-               Set<Authentication> auths = subject.getPrincipals(Authentication.class);
-               if (auths.size() > 0)
-                       SecurityContextHolder.getContext().setAuthentication(
-                                       auths.iterator().next());
+               // Set<Authentication> auths =
+               // subject.getPrincipals(Authentication.class);
+               // if (auths.size() > 0)
+               // SecurityContextHolder.getContext().setAuthentication(
+               // auths.iterator().next());
 
                // thread already logged in
                if (SecurityContextHolder.getContext().getAuthentication() != null)
@@ -80,9 +80,7 @@ public class SpringLoginModule extends SecurityContextLoginModule {
                        callbackHandler.handle(new Callback[] { label, nameCallback,
                                        passwordCallback });
                } catch (Exception e) {
-                       LoginException le = new LoginException("Callback handling failed");
-                       le.initCause(e);
-                       throw le;
+                       throw new RuntimeException("Unexpected exception when handling", e);
                }
 
                // Set user name and password
index 844dc2621d701a7565b80fa8c3df3a38442d8ac7..9d6135fea0de73a15c58cbdbce451e9201f54188 100644 (file)
@@ -9,5 +9,17 @@
             parameter="secureWebUi">
       </entrypoint>
    </extension>
+   <extension
+         id="secureWebapp"
+         name="Argeo Secure Web App"
+         point="org.eclipse.core.runtime.applications">
+      <application cardinality="singleton-global"
+         thread="main"
+         visible="true">
+         <run
+               class="org.argeo.security.ui.rap.SecureEntryPoint">
+         </run>
+      </application>
+   </extension>
 
 </plugin>
index 569412bd619893c638f546539aeb58fc8ea81fb8..f47eb82d4f20c33827c696c324f4de35b3582119 100644 (file)
@@ -1,13 +1,9 @@
 package org.argeo.security.ui.rap;
 
-import java.security.Principal;
+import java.security.AccessController;
 
 import javax.security.auth.Subject;
-import javax.security.auth.login.LoginException;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
 import org.eclipse.jface.action.Action;
 import org.eclipse.jface.action.GroupMarker;
 import org.eclipse.jface.action.IAction;
@@ -17,19 +13,17 @@ import org.eclipse.jface.action.IToolBarManager;
 import org.eclipse.jface.action.MenuManager;
 import org.eclipse.jface.action.Separator;
 import org.eclipse.jface.action.ToolBarManager;
-import org.eclipse.rwt.RWT;
 import org.eclipse.swt.SWT;
 import org.eclipse.ui.IWorkbenchActionConstants;
 import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.actions.ActionFactory;
 import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
 import org.eclipse.ui.application.ActionBarAdvisor;
 import org.eclipse.ui.application.IActionBarConfigurer;
 
 public class SecureActionBarAdvisor extends ActionBarAdvisor {
-       private final static Log log = LogFactory
-                       .getLog(SecureActionBarAdvisor.class);
+//     private final static Log log = LogFactory
+//                     .getLog(SecureActionBarAdvisor.class);
 
        private IAction logoutAction;
        private IWorkbenchAction openPerspectiveDialogAction;
@@ -53,7 +47,8 @@ public class SecureActionBarAdvisor extends ActionBarAdvisor {
                register(showViewMenuAction);
 
                // logout
-               logoutAction = createLogoutAction();
+               logoutAction = ActionFactory.QUIT.create(window);
+               //logoutAction = createLogoutAction();
                register(logoutAction);
 
                // Save semantics
@@ -67,13 +62,9 @@ public class SecureActionBarAdvisor extends ActionBarAdvisor {
        }
 
        protected IAction createLogoutAction() {
-               Subject subject = null;
-               try {
-                       subject = SecureRapActivator.getLoginContext().getSubject();
-               } catch (LoginException e1) {
-                       throw new ArgeoException("Cannot retrieve subject", e1);
-               }
-               final Principal principal = subject.getPrincipals().iterator().next();
+               Subject subject = Subject.getSubject(AccessController.getContext());
+               final String username = subject.getPrincipals().iterator().next()
+                               .getName();
 
                IAction logoutAction = new Action() {
                        public String getId() {
@@ -81,27 +72,28 @@ public class SecureActionBarAdvisor extends ActionBarAdvisor {
                        }
 
                        public String getText() {
-                               return "Logout " + principal.getName();
+                               return "Logout " + username;
                        }
 
                        public void run() {
-                               try {
-                                       Subject subject = SecureRapActivator.getLoginContext()
-                                                       .getSubject();
-                                       String subjectStr = subject.toString();
-                                       subject.getPrincipals().clear();
-                                       SecureRapActivator.getLoginContext().logout();
-                                       log.info(subjectStr + " logged out");
-                               } catch (LoginException e) {
-                                       log.error("Error when logging out", e);
-                               }
-                               try {
-                                       RWT.getRequest().getSession().setMaxInactiveInterval(1);
-                                       PlatformUI.getWorkbench().close();
-                               } catch (Exception e) {
-                                       if (log.isTraceEnabled())
-                                               log.trace("Error when invalidating session", e);
-                               }
+                               // try {
+                               // Subject subject = SecureRapActivator.getLoginContext()
+                               // .getSubject();
+                               // String subjectStr = subject.toString();
+                               // subject.getPrincipals().clear();
+                               // SecureRapActivator.getLoginContext().logout();
+                               // log.info(subjectStr + " logged out");
+                               // } catch (LoginException e) {
+                               // log.error("Error when logging out", e);
+                               // }
+//                             SecureEntryPoint.logout(username);
+//                             PlatformUI.getWorkbench().close();
+                               // try {
+                               // RWT.getRequest().getSession().setMaxInactiveInterval(1);
+                               // } catch (Exception e) {
+                               // if (log.isTraceEnabled())
+                               // log.trace("Error when invalidating session", e);
+                               // }
                        }
 
                };
index f30f0059bd825516bdc77cff250d9bb6d5ed14f1..638b33a12ef0d0aea8738350ae536305b37407a6 100644 (file)
@@ -7,7 +7,8 @@ import javax.security.auth.login.LoginException;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.argeo.eclipse.ui.dialogs.Error;
+import org.eclipse.equinox.security.auth.ILoginContext;
+import org.eclipse.rwt.RWT;
 import org.eclipse.rwt.lifecycle.IEntryPoint;
 import org.eclipse.rwt.service.SessionStoreEvent;
 import org.eclipse.rwt.service.SessionStoreListener;
@@ -18,52 +19,108 @@ import org.eclipse.ui.application.WorkbenchAdvisor;
 import org.eclipse.ui.application.WorkbenchWindowAdvisor;
 
 public class SecureEntryPoint implements IEntryPoint, SessionStoreListener {
-       private Log log = LogFactory.getLog(SecureEntryPoint.class);
+       private final static Log log = LogFactory.getLog(SecureEntryPoint.class);
 
        @Override
        public int createUI() {
-               // log.debug("THREAD=" + Thread.currentThread().getId()
-               // + ", RWT.getSessionStore().getId()="
-               // + RWT.getSessionStore().getId());
+               // 15 mins session timeout
+               RWT.getRequest().getSession().setMaxInactiveInterval(15 * 60);
 
+               if (log.isDebugEnabled())
+                       log.debug("THREAD=" + Thread.currentThread().getId()
+                                       + ", sessionStore=" + RWT.getSessionStore().getId());
+
+               final ILoginContext loginContext = SecureRapActivator
+                               .createLoginContext();
                Integer returnCode = null;
                Display display = PlatformUI.createDisplay();
+
+               Subject subject = null;
                try {
-                       Subject subject = null;
-                       Boolean retry = true;
-                       while (retry) {
+                       loginContext.login();
+                       subject = loginContext.getSubject();
+               } catch (LoginException e) {
+                       log.error("Error when logging in.", e);
+                       display.dispose();
+                       RWT.getRequest().getSession().setMaxInactiveInterval(1);
+                       try {
+                               Thread.sleep(2000);
+                       } catch (InterruptedException e1) {
+                               // silent
+                       }
+                       return -1;
+               }
+
+               // identify after successful login
+               if (log.isDebugEnabled())
+                       log.debug("subject=" + subject);
+               final String username = subject.getPrincipals().iterator().next()
+                               .getName();
+               if (log.isDebugEnabled())
+                       log.debug(username + " logged in");
+               display.disposeExec(new Runnable() {
+                       public void run() {
+                               log.debug("Display disposed");
+                               logout(loginContext, username);
+                               // invalidate session
+                               RWT.getRequest().getSession().setMaxInactiveInterval(1);
                                try {
-                                       // force login in order to give Spring Security a chance to
-                                       // load
-                                       SecureRapActivator.getLoginContext().login();
-                                       subject = SecureRapActivator.getLoginContext().getSubject();
-                                       retry = false;
-                               } catch (LoginException e) {
-                                       Error.show("Cannot login", e);
-                                       retry = true;
-                               } catch (Exception e) {
-                                       Error.show("Unexpected exception while trying to login", e);
-                                       retry = false;
+                                       Thread.sleep(2000);
+                               } catch (InterruptedException e1) {
+                                       // silent
                                }
                        }
+               });
 
-                       if (subject != null) {
-                               returnCode = (Integer) Subject.doAs(subject,
-                                               getRunAction(display));
-                               SecureRapActivator.getLoginContext().logout();
-                               return processReturnCode(returnCode);
-                       } else {
-                               return -1;
-                       }
+               try {
+                       returnCode = (Integer) Subject.doAs(subject, getRunAction(display));
+                       loginContext.logout();
+                       return processReturnCode(returnCode);
                } catch (Exception e) {
-                       log.error("Unexpected error",e);
-                       return -1;
-               } 
-//             finally {
-//                     display.dispose();
-//             }
+                       if (subject != null)
+                               logout(loginContext, username);
+                       // RWT.getRequest().getSession().setMaxInactiveInterval(1);
+                       log.error("Unexpected error", e);
+                       // throw new ArgeoException("Cannot login", e);
+               } finally {
+                       display.dispose();
+               }
+               return -1;
        }
 
+       static void logout(ILoginContext secureContext, String username) {
+               try {
+                       secureContext.logout();
+                       log.info("Logged out " + (username != null ? username : "")
+                                       + " (THREAD=" + Thread.currentThread().getId() + ")");
+               } catch (LoginException e) {
+                       log.error("Erorr when logging out", e);
+               }
+       }
+
+       // static void closeWorkbench() {
+       // final IWorkbench workbench;
+       // try {
+       // workbench = PlatformUI.getWorkbench();
+       // } catch (Exception e) {
+       // return;
+       // }
+       // if (workbench == null)
+       // return;
+       // final Display display = workbench.getDisplay();
+       // if (display != null && !display.isDisposed())
+       // display.syncExec(new Runnable() {
+       //
+       // public void run() {
+       // if (!display.isDisposed())
+       // workbench.close();
+       // }
+       // });
+       //
+       // if (log.isDebugEnabled())
+       // log.debug("Workbench closed");
+       // }
+
        @SuppressWarnings("rawtypes")
        private PrivilegedAction getRunAction(final Display display) {
                return new PrivilegedAction() {
index b8c66cda35b92964d0c8ffbc3c4487d95ca7de16..2a29ba7e0e480420266da5c7e2814b592cdbcb25 100644 (file)
@@ -2,7 +2,6 @@ package org.argeo.security.ui.rap;
 
 import java.net.URL;
 
-import org.argeo.ArgeoException;
 import org.eclipse.equinox.security.auth.ILoginContext;
 import org.eclipse.equinox.security.auth.LoginContextFactory;
 import org.osgi.framework.BundleActivator;
@@ -14,21 +13,29 @@ public class SecureRapActivator implements BundleActivator {
        public final static String CONTEXT_SPRING = "SPRING";
        private static final String JAAS_CONFIG_FILE = "/META-INF/jaas_default.txt";
 
-       private static ILoginContext loginContext = null;
+       //private static ILoginContext loginContext = null;
+       
+       private static BundleContext bundleContext;
 
        public void start(BundleContext bundleContext) throws Exception {
-               URL configUrl = bundleContext.getBundle().getEntry(JAAS_CONFIG_FILE);
-               loginContext = LoginContextFactory.createContext(CONTEXT_SPRING,
-                               configUrl);
+               SecureRapActivator.bundleContext = bundleContext;
+//             URL configUrl = bundleContext.getBundle().getEntry(JAAS_CONFIG_FILE);
+//             loginContext = LoginContextFactory.createContext(CONTEXT_SPRING,
+//                             configUrl);
        }
 
        public void stop(BundleContext context) throws Exception {
        }
 
-       static ILoginContext getLoginContext() {
-               if (loginContext == null)
-                       throw new ArgeoException(
-                                       "No Equinox login context available, check your configuration");
-               return loginContext;
+//     static ILoginContext getLoginContext() {
+//             if (loginContext == null)
+//                     throw new ArgeoException(
+//                                     "No Equinox login context available, check your configuration");
+//             return loginContext;
+//     }
+
+       static ILoginContext createLoginContext() {
+               URL configUrl = bundleContext.getBundle().getEntry(JAAS_CONFIG_FILE);
+               return LoginContextFactory.createContext(CONTEXT_SPRING, configUrl);
        }
 }
index 19affc85431009fd36fedaf348c50da0fa3e3150..96f0535d93ee9181396dd950a610242ace68cfce 100644 (file)
@@ -26,6 +26,7 @@ public class DefaultLoginDialog extends AbstractLoginDialog {
 
        protected DefaultLoginDialog(Shell parentShell) {
                super(parentShell);
+               // setBlockOnOpen(false);
        }
 
        protected Point getInitialSize() {
@@ -109,4 +110,35 @@ public class DefaultLoginDialog extends AbstractLoginDialog {
 
        public void internalHandle() {
        }
+
+       // hack to simulate modal
+       // see
+       // http://dev.eclipse.org/mhonarc/newsLists/news.eclipse.platform.jface/msg00181.html
+       // protected void setShellStyle(int newShellStyle) {
+       // // turn off APPLICATION_MODAL
+       // int newstyle = newShellStyle & ~SWT.APPLICATION_MODAL;
+       // // turn on MODELESS
+       // newstyle |= SWT.MODELESS;
+       // super.setShellStyle(newstyle);
+       // }
+       //
+       // public int open() {
+       //
+       // int retVal = super.open();
+       // // this will let the caller wait till OK, Cancel is
+       // // pressed, but will let the other GUI responsive
+       // pumpMessages();
+       // return retVal;
+       // }
+       //
+       // protected void pumpMessages() {
+       // Shell sh = getShell();
+       // Display disp = sh.getDisplay();
+       // while (!sh.isDisposed()) {
+       // if (!disp.readAndDispatch())
+       // disp.sleep();
+       // }
+       // disp.update();
+       // }
+
 }