X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.security.ui.rap%2Fsrc%2Forg%2Fargeo%2Fsecurity%2Fui%2Frap%2FSecureEntryPoint.java;h=a681527f773e67663c0150576d67324a267a6c09;hb=8260f4470f514ea347ca53f5b4dfc632c4a4de66;hp=fb885377fed8e64e762fe6b24247eeda4176e265;hpb=93a457cf047cebb0170abd0f37a9b4291a2ae3e9;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java b/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java index fb885377f..a681527f7 100644 --- a/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java +++ b/org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java @@ -15,44 +15,42 @@ */ package org.argeo.security.ui.rap; +import java.security.AccessControlContext; +import java.security.AccessController; import java.security.PrivilegedAction; import javax.security.auth.Subject; -import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.CredentialNotFoundException; +import javax.security.auth.login.FailedLoginException; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import javax.security.auth.x500.X500Principal; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.cms.KernelHeader; -import org.argeo.cms.auth.ArgeoLoginContext; +import org.argeo.cms.CmsException; +import org.argeo.cms.auth.AuthConstants; +import org.argeo.cms.auth.ThreadDeathLoginException; import org.argeo.cms.widgets.auth.DefaultLoginDialog; import org.argeo.eclipse.ui.dialogs.ErrorFeedback; -import org.argeo.util.LocaleUtils; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.rap.rwt.RWT; import org.eclipse.rap.rwt.application.EntryPoint; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; -import org.springframework.security.authentication.BadCredentialsException; /** * RAP entry point with login capabilities. Once the user has been * authenticated, the workbench is run as a privileged action by the related * subject. */ +@Deprecated public class SecureEntryPoint implements EntryPoint { + final static String ACCESS_CONTROL_CONTEXT = "org.argeo.node.accessControlContext"; private final static Log log = LogFactory.getLog(SecureEntryPoint.class); - /** - * From org.springframework.security.context. - * HttpSessionContextIntegrationFilter - */ - protected static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT"; - /** * How many seconds to wait before invalidating the session if the user has * not yet logged in. @@ -73,63 +71,67 @@ public class SecureEntryPoint implements EntryPoint { // around too long RWT.getRequest().getSession().setMaxInactiveInterval(loginTimeout); - // Try to load security context thanks to the session processing filter - // HttpServletRequest httpRequest = RWT.getRequest(); - // HttpSession httpSession = httpRequest.getSession(); - // Object contextFromSessionObject = httpSession - // .getAttribute(SPRING_SECURITY_CONTEXT_KEY); - // if (contextFromSessionObject != null) - // SecurityContextHolder - // .setContext((SecurityContext) contextFromSessionObject); - final Display display = PlatformUI.createDisplay(); - Subject subject = new Subject(); - final LoginContext loginContext; - try { - CallbackHandler callbackHandler = new DefaultLoginDialog( - display.getActiveShell()); - loginContext = new ArgeoLoginContext( - KernelHeader.LOGIN_CONTEXT_USER, subject, callbackHandler); - } catch (LoginException e1) { - throw new ArgeoException("Cannot initialize login context", e1); - } + // load context from session + HttpServletRequest httpRequest = RWT.getRequest(); + final HttpSession httpSession = httpRequest.getSession(); + AccessControlContext acc = (AccessControlContext) httpSession + .getAttribute(ACCESS_CONTROL_CONTEXT); + + final Subject subject; + if (acc != null + && Subject.getSubject(acc).getPrincipals(X500Principal.class) + .size() == 1) { + subject = Subject.getSubject(acc); + } else { + subject = new Subject(); - tryLogin: while (subject.getPrincipals(X500Principal.class).size() == 0) { + final LoginContext loginContext; + DefaultLoginDialog callbackHandler; try { - loginContext.login(); - if (subject.getPrincipals(X500Principal.class).size() == 0) - throw new ArgeoException("Login succeeded but no auth");// fatal - - // add security context to session - // if (httpSession.getAttribute(SPRING_SECURITY_CONTEXT_KEY) == - // null) - // httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, - // SecurityContextHolder.getContext()); + callbackHandler = new DefaultLoginDialog( + display.getActiveShell()); + loginContext = new LoginContext( + AuthConstants.LOGIN_CONTEXT_USER, subject, + callbackHandler); + } catch (LoginException e1) { + throw new CmsException("Cannot initialize login context", e1); + } - // add thread locale to RWT session - if (log.isTraceEnabled()) - log.trace("Locale " + LocaleUtils.threadLocale.get()); - RWT.setLocale(LocaleUtils.threadLocale.get()); - - // once the user is logged in, longer session timeout - RWT.getRequest().getSession() - .setMaxInactiveInterval(sessionTimeout); - - if (log.isDebugEnabled()) - log.debug("Authenticated " + subject); - } catch (LoginException e) { - BadCredentialsException bce = wasCausedByBadCredentials(e); - if (bce != null) { + tryLogin: while (subject.getPrincipals(X500Principal.class).size() == 0) { + try { + loginContext.login(); + if (subject.getPrincipals(X500Principal.class).size() == 0) + throw new CmsException("Login succeeded but no auth");// fatal + + // add thread locale to RWT session + // if (log.isTraceEnabled()) + // log.trace("Locale " + LocaleUtils.threadLocale.get()); + // RWT.setLocale(LocaleUtils.threadLocale.get()); + + // once the user is logged in, longer session timeout + RWT.getRequest().getSession() + .setMaxInactiveInterval(sessionTimeout); + + if (log.isDebugEnabled()) + log.debug("Authenticated " + subject); + } catch (FailedLoginException e) { + MessageDialog.openInformation(display.getActiveShell(), + "Bad Credentials", e.getMessage()); + // retry login + continue tryLogin; + } catch (CredentialNotFoundException e) { MessageDialog.openInformation(display.getActiveShell(), - "Bad Credentials", bce.getMessage()); + "No Credentials", e.getMessage()); // retry login continue tryLogin; + } catch (LoginException e) { + callbackHandler.getShell().dispose(); + return processLoginDeath(display, e); } - return processLoginDeath(display, e); } } - final String username = subject.getPrincipals(X500Principal.class) .iterator().next().getName(); // Logout callback when the display is disposed @@ -138,6 +140,8 @@ public class SecureEntryPoint implements EntryPoint { if (log.isTraceEnabled()) log.trace("Display disposed"); try { + LoginContext loginContext = new LoginContext( + AuthConstants.LOGIN_CONTEXT_USER, subject); loginContext.logout(); } catch (LoginException e) { log.error("Error when logging out", e); @@ -152,6 +156,11 @@ public class SecureEntryPoint implements EntryPoint { try { returnCode = Subject.doAs(subject, new PrivilegedAction() { public Integer run() { + // add security context to session + httpSession.setAttribute(ACCESS_CONTROL_CONTEXT, + AccessController.getContext()); + + // start workbench RapWorkbenchAdvisor workbenchAdvisor = createRapWorkbenchAdvisor(username); int result = PlatformUI.createAndRunWorkbench(display, workbenchAdvisor); @@ -159,14 +168,14 @@ public class SecureEntryPoint implements EntryPoint { } }); // Explicit exit from workbench - fullLogout(loginContext, username); + fullLogout(subject, username); } finally { display.dispose(); } return returnCode; } - private Integer processLoginDeath(Display display, LoginException e) { + private Integer processLoginDeath(Display display, Throwable e) { // check thread death ThreadDeath td = wasCausedByThreadDeath(e); if (td != null) { @@ -180,26 +189,12 @@ public class SecureEntryPoint implements EntryPoint { display.dispose(); return -1; } else { - throw new ArgeoException( + throw new CmsException( "Unexpected exception during authentication", e); } } - /** Recursively look for {@link BadCredentialsException} in the root causes. */ - private BadCredentialsException wasCausedByBadCredentials(Throwable t) { - if (t instanceof BadCredentialsException) - return (BadCredentialsException) t; - - if (t instanceof CredentialNotFoundException) - return new BadCredentialsException("Login canceled"); - - if (t.getCause() != null) - return wasCausedByBadCredentials(t.getCause()); - else - return null; - } - /** * If there is a {@link ThreadDeath} in the root causes, rethrow it * (important for RAP cleaning mechanism) @@ -207,21 +202,22 @@ public class SecureEntryPoint implements EntryPoint { protected ThreadDeath wasCausedByThreadDeath(Throwable t) { if (t instanceof ThreadDeath) return (ThreadDeath) t; - + if (t instanceof ThreadDeathLoginException) + return ((ThreadDeathLoginException) t).getThreadDeath(); if (t.getCause() != null) return wasCausedByThreadDeath(t.getCause()); else return null; } - private void fullLogout(LoginContext loginContext, String username) { + private void fullLogout(Subject subject, String username) { try { + LoginContext loginContext = new LoginContext( + AuthConstants.LOGIN_CONTEXT_USER, subject); loginContext.logout(); - // SecurityContextHolder.clearContext(); - - // HttpServletRequest httpRequest = RWT.getRequest(); - // HttpSession httpSession = httpRequest.getSession(); - // httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, null); + HttpServletRequest httpRequest = RWT.getRequest(); + HttpSession httpSession = httpRequest.getSession(); + httpSession.setAttribute(ACCESS_CONTROL_CONTEXT, null); RWT.getRequest().getSession().setMaxInactiveInterval(1); log.info("Logged out " + (username != null ? username : "") + " (THREAD=" + Thread.currentThread().getId() + ")");