[gatein-commits] gatein SVN: r8071 - epp/portal/branches/EPP_5_2_Branch/component/web/security/src/main/java/org/exoplatform/web/security.
do-not-reply at jboss.org
do-not-reply at jboss.org
Tue Nov 15 04:22:59 EST 2011
Author: mposolda
Date: 2011-11-15 04:22:58 -0500 (Tue, 15 Nov 2011)
New Revision: 8071
Modified:
epp/portal/branches/EPP_5_2_Branch/component/web/security/src/main/java/org/exoplatform/web/security/PortalLoginModule.java
Log:
JBEPP-729 - Problem with credentials in HTTP session
Modified: epp/portal/branches/EPP_5_2_Branch/component/web/security/src/main/java/org/exoplatform/web/security/PortalLoginModule.java
===================================================================
--- epp/portal/branches/EPP_5_2_Branch/component/web/security/src/main/java/org/exoplatform/web/security/PortalLoginModule.java 2011-11-15 09:05:45 UTC (rev 8070)
+++ epp/portal/branches/EPP_5_2_Branch/component/web/security/src/main/java/org/exoplatform/web/security/PortalLoginModule.java 2011-11-15 09:22:58 UTC (rev 8071)
@@ -22,6 +22,9 @@
import org.exoplatform.container.ExoContainer;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
+import org.exoplatform.services.security.Authenticator;
+import org.exoplatform.services.security.Identity;
+import org.exoplatform.services.security.UsernameCredential;
import org.exoplatform.services.security.jaas.AbstractLoginModule;
import org.exoplatform.web.login.InitiateLoginServlet;
import org.gatein.wci.security.Credentials;
@@ -34,14 +37,9 @@
import java.lang.reflect.Method;
/**
- * A login module implementation that relies on the token store to check the
- * password validity. If the token store provides a valid {@link Credentials}
- * value then password stacking is used and the two entries are added in the
- * shared state map. The first entry is keyed by
- * <code>javax.security.auth.login.name</code> and contains the
- * {@link Credentials#getUsername()} value, the second entry is keyed by
- * <code>javax.security.auth.login.password</code> and contains the
- * {@link Credentials#getPassword()} ()} value.
+ * A login module implementation that is used to handle reauthentication of client with same HTTP session on various cluster nodes.
+ * After login of user on cluster node is attribute "authenticatedCredentials" added to HTTP session in method {@link #commit()}.
+ * Other cluster nodes can than read these credentials in method {@link #login()}, and can reuse them to relogin.
*
* @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
* @version $Revision$
@@ -58,23 +56,21 @@
static
{
Method getContext = null;
- if (isClusteredSSO())
+
+ log.debug("About to configure PortalLoginModule");
+ try
{
- log.debug("About to configure clustered SSO");
- try
- {
- Class<?> policyContextClass = Thread.currentThread().getContextClassLoader().loadClass("javax.security.jacc.PolicyContext");
- getContext = policyContextClass.getDeclaredMethod("getContext", String.class);
- }
- catch (ClassNotFoundException ignore)
- {
- log.debug("JACC not found ignoring it", ignore);
- }
- catch (Exception e)
- {
- log.error("Could not obtain JACC get context method", e);
- }
+ Class<?> policyContextClass = Thread.currentThread().getContextClassLoader().loadClass("javax.security.jacc.PolicyContext");
+ getContext = policyContextClass.getDeclaredMethod("getContext", String.class);
}
+ catch (ClassNotFoundException ignore)
+ {
+ log.debug("JACC not found ignoring it", ignore);
+ }
+ catch (Exception e)
+ {
+ log.error("Could not obtain JACC get context method", e);
+ }
//
getContextMethod = getContext;
@@ -82,61 +78,58 @@
public static final String AUTHENTICATED_CREDENTIALS = "authenticatedCredentials";
+ private static final String LOGIN_ON_DIFFERENT_NODE = "PortalLoginModule.loginOnDifferentNode";
+
/**
* @see javax.security.auth.spi.LoginModule#login()
*/
@SuppressWarnings("unchecked")
public boolean login() throws LoginException
{
-
- Callback[] callbacks = new Callback[2];
- callbacks[0] = new NameCallback("Username");
- callbacks[1] = new PasswordCallback("Password", false);
-
- try
+ if (getContextMethod != null)
{
- callbackHandler.handle(callbacks);
- String password = new String(((PasswordCallback)callbacks[1]).getPassword());
+ Credentials authCredentials = null;
- Credentials c = null;
-
- //
- // For clustered config check credentials stored and propagated in session. This won't work in tomcat because
- // of lack of JACC PolicyContext so the code must be a bit defensive
- if (getContextMethod != null && password.startsWith(InitiateLoginServlet.COOKIE_NAME))
+ try
{
- HttpServletRequest request;
- try
+ HttpServletRequest request = (HttpServletRequest)getContextMethod.invoke(null, "javax.servlet.http.HttpServletRequest");
+ authCredentials = (Credentials)request.getSession().getAttribute(AUTHENTICATED_CREDENTIALS);
+
+ // If authenticated credentials were presented in HTTP session, it means that we were already logged on different cluster node
+ // with this HTTP session. We don't need to validate password again in this case (We don't have password anyway)
+ if (authCredentials != null)
{
- request = (HttpServletRequest)getContextMethod.invoke(null, "javax.servlet.http.HttpServletRequest");
- Object o = request.getSession().getAttribute(AUTHENTICATED_CREDENTIALS);
-
- if (o instanceof Credentials)
+ Authenticator authenticator = (Authenticator)getContainer().getComponentInstanceOfType(Authenticator.class);
+ if (authenticator == null)
{
- c = (Credentials) o;
+ throw new LoginException("No Authenticator component found, check your configuration");
}
+
+ String username = authCredentials.getUsername();
+ Identity identity = authenticator.createIdentity(username);
+
+ sharedState.put("exo.security.identity", identity);
+ sharedState.put("javax.security.auth.login.name", username);
+
+ subject.getPublicCredentials().add(new UsernameCredential(username));
+
+ // Add empty password to subject and remove password key, so that SharedStateLoginModule won't be processed
+ subject.getPrivateCredentials().add("");
+ sharedState.remove("javax.security.auth.login.password");
+
+ // Add flag that we were logged with real password on different cluster node. Not on this node.
+ sharedState.put(LOGIN_ON_DIFFERENT_NODE, true);
}
- catch(Throwable e)
- {
- log.error(this,e);
- log.error("LoginModule error. Turn off session credentials checking with proper configuration option of " +
- "LoginModule set to false");
- }
}
-
- if (c != null)
+ catch(Exception e)
{
- sharedState.put("javax.security.auth.login.name", c.getUsername());
- sharedState.put("javax.security.auth.login.password", c.getPassword());
+ log.error(this, e);
+ LoginException le = new LoginException(e.getMessage());
+ le.initCause(e);
+ throw le;
}
- return true;
}
- catch (Exception e)
- {
- LoginException le = new LoginException();
- le.initCause(e);
- throw le;
- }
+ return true;
}
/**
@@ -144,21 +137,22 @@
*/
public boolean commit() throws LoginException
{
-
+ // Add authenticated credentials to session only if we were logged on this host with "real" credentials
if (getContextMethod != null &&
sharedState.containsKey("javax.security.auth.login.name") &&
- sharedState.containsKey("javax.security.auth.login.password"))
+ sharedState.containsKey("javax.security.auth.login.password") &&
+ sharedState.get(LOGIN_ON_DIFFERENT_NODE) == null)
{
String uid = (String)sharedState.get("javax.security.auth.login.name");
- String pass = (String)sharedState.get("javax.security.auth.login.password");
- Credentials wc = new Credentials(uid, pass);
+ Credentials wc = new Credentials(uid, "");
HttpServletRequest request = null;
try
{
request = (HttpServletRequest)getContextMethod.invoke(null, "javax.servlet.http.HttpServletRequest");
request.getSession().setAttribute(AUTHENTICATED_CREDENTIALS, wc);
+ handleCredentialsRemoving(request);
}
catch(Exception e)
{
@@ -196,4 +190,15 @@
{
return ExoContainer.getProfiles().contains("cluster");
}
+
+ /**
+ * Remove credentials of authenticated user from HTTP session.
+ *
+ * @param request httpRequest
+ */
+ protected void handleCredentialsRemoving(HttpServletRequest request)
+ {
+ // TODO: We can't remove credentials from HTTP session right now because WSRP-Security relies on it. See method WSSecurityCredentialHelper.handleRequest
+ // request.getSession().removeAttribute(Credentials.CREDENTIALS);
+ }
}
More information about the gatein-commits
mailing list