private final Throwable exception;
public static void show(String message, Throwable e) {
+ // rethrow ThreaDeath in order to make sure that RAP will properly clean
+ // up the UI thread
+ if (e instanceof ThreadDeath)
+ throw (ThreadDeath) e;
+
new Error(getDisplay().getActiveShell(), message, e).open();
}
/** Tries to find a display */
private static Display getDisplay() {
try {
- return PlatformUI.getWorkbench().getDisplay();
+ Display display = PlatformUI.getWorkbench().getDisplay();
+ if (display != null)
+ return display;
+ else
+ return Display.getDefault();
} catch (Exception e) {
return Display.getCurrent();
}
<property name="userDetailsContextMapper" ref="jcrUserDetailsContextMapper" />
</bean>
+<!-- <bean id="ldapAuthenticator" -->
+<!-- class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator"> -->
+<!-- <constructor-arg ref="contextSource" /> -->
+<!-- <property name="userDnPatterns"> -->
+<!-- <list> -->
+<!-- <value><![CDATA[${argeo.ldap.usernameAttribute}={0},${argeo.ldap.userBase}]]></value> -->
+<!-- </list> -->
+<!-- </property> -->
+<!-- </bean> -->
+
+ <!-- PasswordComparisonAuthenticator doesn't work with SSHA -->
<bean id="ldapAuthenticator"
- class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator">
+ class="org.springframework.security.providers.ldap.authenticator.PasswordComparisonAuthenticator">
<constructor-arg ref="contextSource" />
<property name="userDnPatterns">
<list>
<value><![CDATA[${argeo.ldap.usernameAttribute}={0},${argeo.ldap.userBase}]]></value>
</list>
</property>
+ <property name="passwordAttributeName" value="${argeo.ldap.passwordAttribute}" />
+ <property name="passwordEncoder" ref="passwordEncoder" />
</bean>
- <!-- DOESN'T WORK WITH SSHA -->
- <!-- <bean id="passwordComparisonAuthenticator" -->
- <!-- class="org.springframework.security.providers.ldap.authenticator.PasswordComparisonAuthenticator"> -->
- <!-- <constructor-arg ref="contextSource" /> -->
- <!-- <property name="userDnPatterns"> -->
- <!-- <list> -->
- <!-- <value><![CDATA[${argeo.ldap.usernameAttribute}={0},${argeo.ldap.userBase}]]></value> -->
- <!-- </list> -->
- <!-- </property> -->
- <!-- <property name="passwordAttributeName" value="${argeo.ldap.passwordAttribute}"
- /> -->
- <!-- <property name="passwordEncoder" ref="passwordEncoder" /> -->
- <!-- </bean> -->
-
<!-- USER DETAILS -->
<bean id="userAdminDao" class="org.argeo.security.ldap.ArgeoSecurityDaoLdap">
<constructor-arg ref="contextSource" />
--- /dev/null
+<html>
+<head></head>
+<body>
+<center>
+<table height="100%">
+<tr>
+ <td style="vertical-align:middle">
+ <a style="font-family:sans-serif;color:#0066CC;text-decoration:none;" href="./secureWebUi">Login...</a>
+ </td>
+</tr>
+</table>
+</center>
+</body>
+</html>
\ No newline at end of file
bin.includes = plugin.xml,\
- META-INF/
+ META-INF/,\
+ branding/
source.. = src/main/java/
output.. = target/classes/
</application>
</extension>
+ <extension
+ point="org.eclipse.rap.ui.branding">
+ <branding
+ id="org.argeo.security.ui.rap.branding"
+ servletName="secureWebUi"
+ defaultEntrypointId="org.argeo.security.ui.rap.secureEntryPoint"
+ title="Argeo Secure Web UI"
+ favicon="branding/favicon.ico"
+ body="branding/default.htm">
+ </branding>
+ </extension>
+
</plugin>
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
import org.eclipse.equinox.security.auth.ILoginContext;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.rwt.RWT;
final ILoginContext loginContext = SecureRapActivator
.createLoginContext();
Subject subject = null;
- tryLogin: while (subject == null) {
+ tryLogin: while (subject == null && !display.isDisposed()) {
try {
loginContext.login();
subject = loginContext.getSubject();
} catch (LoginException e) {
- if (e.getCause() != null) {
- Throwable firstCause = e.getCause();
- // log.error("Cause", firstCause);
- if (firstCause instanceof LoginException
- && firstCause.getCause() != null) {
- Throwable secondCause = firstCause.getCause();
- if (secondCause instanceof BadCredentialsException) {
- MessageDialog.openInformation(
- display.getActiveShell(),
- "Bad Credentials",
- "Your credentials are incorrect");
- // retry login
- continue tryLogin;
- } else if (secondCause instanceof ThreadDeath) {
- // rethrow thread death caused by dialog UI timeout
- throw (ThreadDeath) secondCause;
- }
-
- } else if (firstCause instanceof ThreadDeath) {
- throw (ThreadDeath) firstCause;
- }
+ BadCredentialsException bce = wasCausedByBadCredentials(e);
+ if (bce != null) {
+ MessageDialog.openInformation(display.getActiveShell(),
+ "Bad Credentials", bce.getMessage());
+ // retry login
+ continue tryLogin;
+ }
+
+ // check thread death
+ ThreadDeath td = wasCausedByThreadDeath(e);
+ if (td != null) {
+ display.dispose();
+ throw td;
+ }
+
+ // if (e.getCause() != null) {
+ // Throwable firstCause = e.getCause();
+ // // log.error("Cause", firstCause);
+ // if (firstCause instanceof LoginException
+ // && firstCause.getCause() != null) {
+ // Throwable secondCause = firstCause.getCause();
+ // if (secondCause instanceof BadCredentialsException) {
+ // MessageDialog.openInformation(
+ // display.getActiveShell(),
+ // "Bad Credentials",
+ // "Your credentials are incorrect");
+ // // retry login
+ // continue tryLogin;
+ // } else if (secondCause instanceof ThreadDeath) {
+ // // rethrow thread death caused by dialog UI timeout
+ // throw (ThreadDeath) secondCause;
+ // }
+ //
+ // } else if (firstCause instanceof ThreadDeath) {
+ // throw (ThreadDeath) firstCause;
+ // }
+ // }
+
+ if (!display.isDisposed()) {
+ org.argeo.eclipse.ui.Error.show(
+ "Unexpected exception during authentication", e);
+ // this was not just bad credentials or death thread
+ RWT.getRequest().getSession().setMaxInactiveInterval(1);
+ display.dispose();
+ return -1;
+ } else {
+ throw new ArgeoException(
+ "Unexpected exception during authentication", e);
}
- // this was not just bad credentials returns
- RWT.getRequest().getSession().setMaxInactiveInterval(1);
- display.dispose();
- return -1;
}
}
public void run() {
log.debug("Display disposed");
logout(loginContext, username);
- // invalidate session
- //RWT.getRequest().getSession().setMaxInactiveInterval(1);
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e1) {
- // silent
- }
}
});
return processReturnCode(returnCode);
}
+ /** Recursively look for {@link BadCredentialsException} in the root causes. */
+ private BadCredentialsException wasCausedByBadCredentials(Throwable t) {
+ if (t instanceof BadCredentialsException)
+ return (BadCredentialsException) t;
+
+ 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)
+ */
+ protected ThreadDeath wasCausedByThreadDeath(Throwable t) {
+ if (t instanceof ThreadDeath)
+ return (ThreadDeath) t;
+
+ if (t.getCause() != null)
+ return wasCausedByThreadDeath(t.getCause());
+ else
+ return null;
+ }
+
protected void logout(ILoginContext secureContext, String username) {
try {
secureContext.logout();
// when the OSGi runtime is shut down
try {
Thread.sleep(100);
- if (display.isDisposed()) {
- log.warn("Display is disposed, killing login dialog thread");
- throw new ThreadDeath();
- }
+ // if (display.isDisposed()) {
+ // log.warn("Display is disposed, killing login dialog thread");
+ // throw new ThreadDeath();
+ // }
} catch (final Exception e) {
// do nothing
}
}, true, new NullProgressMonitor(), Display.getDefault());
} catch (ThreadDeath e) {
isCancelled = true;
+ log.debug("Thread " + Thread.currentThread().getId() + " died");
throw e;
} catch (Exception e) {
isCancelled = true;
} finally {
// so that the modal thread dies
processCallbacks = true;
- try {
- // wait for the modal context thread to gracefully exit
- modalContextThread.join(1000);
- } catch (InterruptedException ie) {
- // silent
- }
+ // try {
+ // // wait for the modal context thread to gracefully exit
+ // modalContextThread.join();
+ // } catch (InterruptedException ie) {
+ // // silent
+ // }
modalContextThread = null;
}
}
<includes>
<include>plugin.xml</include>
<include>META-INF/**</include>
+ <include>branding/**</include>
<include>jaas/**</include>
<include>icons/**</include>
</includes>
public void execute(Runnable runnable) {
try {
wrapWithSystemAuthentication(Executors.callable(runnable)).call();
+ } catch (RuntimeException e) {
+ throw e;
} catch (Exception e) {
throw new ArgeoException(
"Exception when running system authenticated task", e);
import org.argeo.security.jcr.JcrUserDetails;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
+import org.springframework.security.BadCredentialsException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.encoding.PasswordEncoder;
/** @return path to the user home node */
protected String mapLdapToJcr(String username, DirContextOperations ctx) {
+ String usernameLdap = ctx.getStringAttribute(usernameAttribute);
+ // log.debug("username=" + username + ", usernameLdap=" + usernameLdap);
+ if (!username.equals(usernameLdap)) {
+ String msg = "Provided username '" + username
+ + "' is different from username stored in LDAP '"
+ + usernameLdap+"'";
+ // we log it because the exception may not be displayed
+ log.error(msg);
+ throw new BadCredentialsException(msg);
+ }
+
try {
+
Node userHome = JcrUtils.getUserHome(session, username);
if (userHome == null)
userHome = JcrUtils.createUserHome(session, homeBasePath,
username);
String userHomePath = userHome.getPath();
- Node userProfile; // = userHome.getNode(ARGEO_PROFILE);
+ Node userProfile; // = userHome.getNode(ARGEO_PROFILE);
if (userHome.hasNode(ARGEO_PROFILE)) {
userProfile = userHome.getNode(ARGEO_PROFILE);
} else {