Author: mposolda
Date: 2011-11-15 09:25:55 -0500 (Tue, 15 Nov 2011)
New Revision: 8073
Added:
portal/trunk/component/web/security/src/main/java/org/exoplatform/web/security/PortalLoginModule.java
Modified:
portal/trunk/component/web/security/src/main/java/org/exoplatform/web/login/ClusteredSSOFilter.java
portal/trunk/examples/portal/ear/src/main/application/META-INF/gatein-jboss-beans.xml
portal/trunk/packaging/jboss-as5/pkg/src/main/resources/jboss/server/default/deploy/gatein.ear/META-INF/gatein-jboss-beans.xml
portal/trunk/packaging/jboss-as6/pkg/src/main/resources/jboss/server/default/deploy/gatein.ear/META-INF/gatein-jboss-beans.xml
Log:
GTNPORTAL-2274 Can't login after unsuccessful login attempt in cluster profile
Modified:
portal/trunk/component/web/security/src/main/java/org/exoplatform/web/login/ClusteredSSOFilter.java
===================================================================
---
portal/trunk/component/web/security/src/main/java/org/exoplatform/web/login/ClusteredSSOFilter.java 2011-11-15
12:21:46 UTC (rev 8072)
+++
portal/trunk/component/web/security/src/main/java/org/exoplatform/web/login/ClusteredSSOFilter.java 2011-11-15
14:25:55 UTC (rev 8073)
@@ -26,6 +26,7 @@
import org.exoplatform.container.ExoContainer;
import org.exoplatform.container.web.AbstractFilter;
+import org.exoplatform.web.security.PortalLoginModule;
import org.gatein.wci.security.Credentials;
import org.jboss.web.tomcat.security.login.WebAuthentication;
@@ -48,7 +49,7 @@
{
HttpServletRequest httpRequest = (HttpServletRequest)request;
- Credentials credentials =
(Credentials)httpRequest.getSession().getAttribute(Credentials.CREDENTIALS);
+ Credentials credentials =
(Credentials)httpRequest.getSession().getAttribute(PortalLoginModule.AUTHENTICATED_CREDENTIALS);
// Make programatic login if authenticated credentials are present in session -
they were set in another cluster node
if (credentials != null && httpRequest.getRemoteUser() == null)
@@ -64,7 +65,7 @@
// This is a workaround... without this code this attr will vanish from session
after first request - don't ask...
if (credentials != null && httpRequest.getSession(false) != null)
{
- httpRequest.getSession(false).setAttribute(Credentials.CREDENTIALS,
credentials);
+
httpRequest.getSession(false).setAttribute(PortalLoginModule.AUTHENTICATED_CREDENTIALS,
credentials);
}
}
else
Added:
portal/trunk/component/web/security/src/main/java/org/exoplatform/web/security/PortalLoginModule.java
===================================================================
---
portal/trunk/component/web/security/src/main/java/org/exoplatform/web/security/PortalLoginModule.java
(rev 0)
+++
portal/trunk/component/web/security/src/main/java/org/exoplatform/web/security/PortalLoginModule.java 2011-11-15
14:25:55 UTC (rev 8073)
@@ -0,0 +1,204 @@
+/*
+ * JBoss, a division of Red Hat
+ * Copyright 2011, Red Hat Middleware, LLC, and individual
+ * contributors as indicated by the @authors tag. See the
+ * copyright.txt in the distribution for a full listing of
+ * individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.exoplatform.web.security;
+
+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.gatein.wci.security.Credentials;
+
+import javax.security.auth.login.LoginException;
+import javax.servlet.http.HttpServletRequest;
+import java.lang.reflect.Method;
+
+/**
+ * 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@exoplatform.com">Julien
Viet</a>
+ * @version $Revision$
+ */
+public class PortalLoginModule extends AbstractLoginModule
+{
+
+ /** Logger. */
+ private static final Log log = ExoLogger.getLogger(PortalLoginModule.class);
+
+ /** JACC get context method. */
+ private static final Method getContextMethod;
+
+ static
+ {
+ Method getContext = null;
+
+ log.debug("About to configure PortalLoginModule");
+ 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);
+ }
+
+ //
+ getContextMethod = getContext;
+ }
+
+ 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
+ {
+ if (getContextMethod != null)
+ {
+ Credentials authCredentials = null;
+
+ 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)
+ {
+ Authenticator authenticator =
(Authenticator)getContainer().getComponentInstanceOfType(Authenticator.class);
+ if (authenticator == null)
+ {
+ 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(Exception e)
+ {
+ log.error(this, e);
+ LoginException le = new LoginException(e.getMessage());
+ le.initCause(e);
+ throw le;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @see javax.security.auth.spi.LoginModule#commit()
+ */
+ 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.get(LOGIN_ON_DIFFERENT_NODE) == null)
+ {
+ String uid =
(String)sharedState.get("javax.security.auth.login.name");
+
+ 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)
+ {
+ log.error(this,e);
+ log.error("LoginModule error. Turn off session credentials checking with
proper configuration option of " +
+ "LoginModule set to false");
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @see javax.security.auth.spi.LoginModule#abort()
+ */
+ public boolean abort() throws LoginException
+ {
+ return true;
+ }
+
+ /**
+ * @see javax.security.auth.spi.LoginModule#logout()
+ */
+ public boolean logout() throws LoginException
+ {
+ return true;
+ }
+
+ @Override
+ protected Log getLogger()
+ {
+ return log;
+ }
+
+ protected static boolean isClusteredSSO()
+ {
+ 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);
+ }
+}
Modified:
portal/trunk/examples/portal/ear/src/main/application/META-INF/gatein-jboss-beans.xml
===================================================================
---
portal/trunk/examples/portal/ear/src/main/application/META-INF/gatein-jboss-beans.xml 2011-11-15
12:21:46 UTC (rev 8072)
+++
portal/trunk/examples/portal/ear/src/main/application/META-INF/gatein-jboss-beans.xml 2011-11-15
14:25:55 UTC (rev 8073)
@@ -6,6 +6,10 @@
<module-option
name="portalContainerName">sample-portal</module-option>
<module-option
name="realmName">gatein-domain-sample-portal</module-option>
</login-module>
+ <login-module code="org.exoplatform.web.security.PortalLoginModule"
flag="required">
+ <module-option
name="portalContainerName">sample-portal</module-option>
+ <module-option
name="realmName">gatein-domain-sample-portal</module-option>
+ </login-module>
<login-module
code="org.exoplatform.services.security.jaas.SharedStateLoginModule"
flag="required">
<module-option
name="portalContainerName">sample-portal</module-option>
<module-option
name="realmName">gatein-domain-sample-portal</module-option>
Modified:
portal/trunk/packaging/jboss-as5/pkg/src/main/resources/jboss/server/default/deploy/gatein.ear/META-INF/gatein-jboss-beans.xml
===================================================================
---
portal/trunk/packaging/jboss-as5/pkg/src/main/resources/jboss/server/default/deploy/gatein.ear/META-INF/gatein-jboss-beans.xml 2011-11-15
12:21:46 UTC (rev 8072)
+++
portal/trunk/packaging/jboss-as5/pkg/src/main/resources/jboss/server/default/deploy/gatein.ear/META-INF/gatein-jboss-beans.xml 2011-11-15
14:25:55 UTC (rev 8073)
@@ -6,6 +6,10 @@
<module-option
name="portalContainerName">portal</module-option>
<module-option
name="realmName">gatein-domain</module-option>
</login-module>
+ <login-module code="org.exoplatform.web.security.PortalLoginModule"
flag="required">
+ <module-option
name="portalContainerName">portal</module-option>
+ <module-option
name="realmName">gatein-domain</module-option>
+ </login-module>
<login-module
code="org.exoplatform.services.security.jaas.SharedStateLoginModule"
flag="required">
<module-option
name="portalContainerName">portal</module-option>
<module-option
name="realmName">gatein-domain</module-option>
Modified:
portal/trunk/packaging/jboss-as6/pkg/src/main/resources/jboss/server/default/deploy/gatein.ear/META-INF/gatein-jboss-beans.xml
===================================================================
---
portal/trunk/packaging/jboss-as6/pkg/src/main/resources/jboss/server/default/deploy/gatein.ear/META-INF/gatein-jboss-beans.xml 2011-11-15
12:21:46 UTC (rev 8072)
+++
portal/trunk/packaging/jboss-as6/pkg/src/main/resources/jboss/server/default/deploy/gatein.ear/META-INF/gatein-jboss-beans.xml 2011-11-15
14:25:55 UTC (rev 8073)
@@ -6,6 +6,10 @@
<module-option
name="portalContainerName">portal</module-option>
<module-option
name="realmName">gatein-domain</module-option>
</login-module>
+ <login-module code="org.exoplatform.web.security.PortalLoginModule"
flag="required">
+ <module-option
name="portalContainerName">portal</module-option>
+ <module-option
name="realmName">gatein-domain</module-option>
+ </login-module>
<login-module
code="org.exoplatform.services.security.jaas.SharedStateLoginModule"
flag="required">
<module-option
name="portalContainerName">portal</module-option>
<module-option
name="realmName">gatein-domain</module-option>