You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2010/02/01 11:57:43 UTC

svn commit: r905248 - in /sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth: impl/ impl/engine/ spi/

Author: fmeschbe
Date: Mon Feb  1 10:57:43 2010
New Revision: 905248

URL: http://svn.apache.org/viewvc?rev=905248&view=rev
Log:
SLING-1314 Apply proposed patch supporting authentication feedback after trying
to login

Added:
    sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationFeedbackHandler.java   (with props)
    sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/DefaultAuthenticationFeedbackHandler.java   (with props)
Modified:
    sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/AbstractAuthenticationHandlerHolder.java
    sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/AuthenticationHandlerHolder.java
    sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/SlingAuthenticator.java
    sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/engine/EngineAuthenticationHandlerHolder.java

Modified: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/AbstractAuthenticationHandlerHolder.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/AbstractAuthenticationHandlerHolder.java?rev=905248&r1=905247&r2=905248&view=diff
==============================================================================
--- sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/AbstractAuthenticationHandlerHolder.java (original)
+++ sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/AbstractAuthenticationHandlerHolder.java Mon Feb  1 10:57:43 2010
@@ -23,6 +23,7 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.sling.commons.auth.spi.AuthenticationFeedbackHandler;
 import org.apache.sling.commons.auth.spi.AuthenticationHandler;
 import org.apache.sling.commons.auth.spi.AuthenticationInfo;
 
@@ -38,6 +39,8 @@
         super(fullPath);
     }
 
+    protected abstract AuthenticationFeedbackHandler getFeedbackHandler();
+
     protected abstract AuthenticationInfo doExtractCredentials(HttpServletRequest request,
             HttpServletResponse response);
 

Modified: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/AuthenticationHandlerHolder.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/AuthenticationHandlerHolder.java?rev=905248&r1=905247&r2=905248&view=diff
==============================================================================
--- sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/AuthenticationHandlerHolder.java (original)
+++ sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/AuthenticationHandlerHolder.java Mon Feb  1 10:57:43 2010
@@ -23,6 +23,7 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.sling.commons.auth.spi.AuthenticationFeedbackHandler;
 import org.apache.sling.commons.auth.spi.AuthenticationHandler;
 import org.apache.sling.commons.auth.spi.AuthenticationInfo;
 
@@ -46,6 +47,14 @@
         this.handler = handler;
     }
 
+    @Override
+    protected AuthenticationFeedbackHandler getFeedbackHandler() {
+        if (handler instanceof AuthenticationFeedbackHandler) {
+            return (AuthenticationFeedbackHandler) handler;
+        }
+        return null;
+    }
+
     public AuthenticationInfo doExtractCredentials(HttpServletRequest request,
             HttpServletResponse response) {
 

Modified: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/SlingAuthenticator.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/SlingAuthenticator.java?rev=905248&r1=905247&r2=905248&view=diff
==============================================================================
--- sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/SlingAuthenticator.java (original)
+++ sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/SlingAuthenticator.java Mon Feb  1 10:57:43 2010
@@ -40,8 +40,10 @@
 import org.apache.sling.commons.auth.Authenticator;
 import org.apache.sling.commons.auth.NoAuthenticationHandlerException;
 import org.apache.sling.commons.auth.impl.engine.EngineAuthenticationHandlerHolder;
+import org.apache.sling.commons.auth.spi.AuthenticationFeedbackHandler;
 import org.apache.sling.commons.auth.spi.AuthenticationHandler;
 import org.apache.sling.commons.auth.spi.AuthenticationInfo;
+import org.apache.sling.commons.auth.spi.DefaultAuthenticationFeedbackHandler;
 import org.apache.sling.commons.osgi.OsgiUtil;
 import org.apache.sling.jcr.api.SlingRepository;
 import org.apache.sling.jcr.api.TooManySessionsException;
@@ -145,6 +147,13 @@
      */
     private static final String REQUEST_ATTRIBUTE_SESSION = "javax.jcr.Session";
 
+    /**
+     * The name of the {@link AuthenticationInfo} property providing the option
+     * {@link org.apache.sling.commons.auth.spi.AuthenticationFeedbackHandler}
+     * handler to be called back on login failure or success.
+     */
+    private static final String AUTH_INFO_PROP_FEEDBACK_HANDLER = "$$sling.auth.AuthenticationFeedbackHandler$$";
+
     private static ArrayList<AbstractAuthenticationHandlerHolder> EMPTY_INFO = new ArrayList<AbstractAuthenticationHandlerHolder>();
 
     /** @scr.reference */
@@ -491,7 +500,12 @@
             if (pathInfo.startsWith(holder.path)) {
                 final AuthenticationInfo authInfo = holder.extractCredentials(
                     request, response);
+
                 if (authInfo != null) {
+                    // add the feedback handler to the info (may be null)
+                    authInfo.put(AUTH_INFO_PROP_FEEDBACK_HANDLER,
+                        holder.getFeedbackHandler());
+
                     return authInfo;
                 }
             }
@@ -506,6 +520,9 @@
     private boolean getSession(final HttpServletRequest request,
             final HttpServletResponse response, final AuthenticationInfo authInfo) {
 
+        // prepare the feedback handler
+        final AuthenticationFeedbackHandler feedbackHandler = (AuthenticationFeedbackHandler) authInfo.remove(AUTH_INFO_PROP_FEEDBACK_HANDLER);
+
         // try to connect
         try {
             Session session = repository.login(authInfo.getCredentials(),
@@ -514,10 +531,25 @@
             // handle impersonation
             session = handleImpersonation(request, response, session);
 
-            // check whether the client asked for redirect after
-            // authentication and/or impersonation
-            if (handleRedirect(request, response)) {
-                return false;
+            // handle success feedback
+            if (feedbackHandler != null) {
+
+                // call the feedback handler, terminating the request if
+                // so desired by the handler
+                if (feedbackHandler.authenticationSucceeded(request, response,
+                    authInfo)) {
+                    return false;
+                }
+
+            } else {
+
+                // if there is no feedback handler: check whether the client
+                // asked for redirect after authentication and/or impersonation
+                if (DefaultAuthenticationFeedbackHandler.handleRedirect(
+                    request, response)) {
+                    return false;
+                }
+
             }
 
             // set the attributes for further processing
@@ -527,6 +559,13 @@
 
         } catch (RepositoryException re) {
 
+            // handle failure feedback before proceeding to handling the
+            // failed login internally
+            if (feedbackHandler != null) {
+                feedbackHandler.authenticationFailed(request, response, authInfo);
+            }
+
+            // now find a way to get credentials
             handleLoginFailure(request, response, authInfo.getUser(), re);
 
         }
@@ -550,7 +589,8 @@
 
                 // check whether the client asked for redirect after
                 // authentication and/or impersonation
-                if (handleRedirect(request, response)) {
+                if (DefaultAuthenticationFeedbackHandler.handleRedirect(
+                    request, response)) {
                     return false;
                 }
 
@@ -860,58 +900,6 @@
     }
 
     /**
-     * Handles an optional request for a redirect after successful
-     * authentication and <code>true</code> if the request has been redirected.
-     * <p>
-     * If sending the redirect response fails due to some IO problems, the
-     * request is still terminated but an error message is logged indicating the
-     * problem.
-     *
-     * @return <code>true</code> if redirect was requested. Otherwise
-     *         <code>false</code> is returned. Note, that <code>true</code> is
-     *         returned regardless of whether sending the redirect response
-     *         succeeded or not.
-     */
-    private boolean handleRedirect(final HttpServletRequest request,
-            final HttpServletResponse response) {
-
-        final String redirect = request.getParameter(REDIRECT_PARAMETER);
-        if (redirect != null) {
-
-            // find the redirect target
-            final String target;
-            if ("true".equalsIgnoreCase(redirect) || redirect.length() == 0) {
-                // redirect to the same path
-                target = request.getRequestURI();
-
-            } else if (redirect.startsWith("/")) {
-                // absolute target (in the servlet context)
-                target = request.getContextPath() + redirect;
-
-            } else {
-                // redirect relative to the current request
-                target = redirect;
-
-            }
-
-            // and redirect ensuring the response is sent to the client
-            try {
-                response.sendRedirect(target);
-            } catch (Exception e) {
-                // expected: IOException and IllegalStateException
-                log.error("handleRedirect: Failed to send redirect to "
-                    + target + ", aborting request without redirect", e);
-            }
-
-            // consider the request done
-            return true;
-        }
-
-        // no redirect requested
-        return false;
-    }
-
-    /**
      * Returns the path to be used to select the authentication handler to login
      * or logout with.
      * <p>

Modified: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/engine/EngineAuthenticationHandlerHolder.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/engine/EngineAuthenticationHandlerHolder.java?rev=905248&r1=905247&r2=905248&view=diff
==============================================================================
--- sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/engine/EngineAuthenticationHandlerHolder.java (original)
+++ sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/impl/engine/EngineAuthenticationHandlerHolder.java Mon Feb  1 10:57:43 2010
@@ -24,6 +24,7 @@
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.sling.commons.auth.impl.AbstractAuthenticationHandlerHolder;
+import org.apache.sling.commons.auth.spi.AuthenticationFeedbackHandler;
 import org.apache.sling.commons.auth.spi.AuthenticationInfo;
 import org.apache.sling.engine.auth.AuthenticationHandler;
 
@@ -46,6 +47,14 @@
         this.handler = handler;
     }
 
+    @Override
+    protected AuthenticationFeedbackHandler getFeedbackHandler() {
+        if (handler instanceof AuthenticationFeedbackHandler) {
+            return (AuthenticationFeedbackHandler) handler;
+        }
+        return null;
+    }
+
     public AuthenticationInfo doExtractCredentials(HttpServletRequest request,
             HttpServletResponse response) {
 

Added: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationFeedbackHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationFeedbackHandler.java?rev=905248&view=auto
==============================================================================
--- sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationFeedbackHandler.java (added)
+++ sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationFeedbackHandler.java Mon Feb  1 10:57:43 2010
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.commons.auth.spi;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * The <code>AuthenticationFeedbackHandler</code> may be implemented by
+ * {@link AuthenticationHandler} services to request being informed on the
+ * success or failure of authentication.
+ */
+public interface AuthenticationFeedbackHandler {
+
+    /**
+     * Called if authentication failed with the credentials provided in the
+     * <code>authInfo</code> map.
+     * <p>
+     * This method allows the handler to cleanup any state prepared while
+     * handling the
+     * {@link AuthenticationHandler#extractCredentials(HttpServletRequest, HttpServletResponse)
+     * extractCredentials} method. Handlers are expected to not send a in this
+     * method because the Sling Authenticator will proceed to select an
+     * authentication handler whose
+     * {@link AuthenticationHandler#requestCredentials(HttpServletRequest, HttpServletResponse)
+     * requestCredentials} method will be called.
+     *
+     * @param request The current request
+     * @param response The current response
+     * @param authInfo The {@link AuthenticationInfo} object used to
+     *            authenticate the request.
+     */
+    void authenticationFailed(HttpServletRequest request,
+            HttpServletResponse response, AuthenticationInfo authInfo);
+
+    /**
+     * Called if authentication succeeded with the credentials provided in the
+     * <code>authInfo</code> map.
+     * <p>
+     * This method is called after successful login and impersonation handling
+     * immediately before continuing with the request. The handler may choose to
+     * send its own response or to just set some response header (e.g. adding a
+     * Cookie) and return appropriately.
+     *
+     * @param request The current request
+     * @param response The current response
+     * @param authInfo The {@link AuthenticationInfo} object used to
+     *            authenticate the request.
+     * @return <code>true</code> if the handler sent back a response to the
+     *         client and request processing should be terminated at this point.
+     *         If <code>false</code> is returned, the request proceeds as
+     *         authenticated.
+     */
+    boolean authenticationSucceeded(HttpServletRequest request,
+            HttpServletResponse response, AuthenticationInfo authInfo);
+}

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationFeedbackHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/AuthenticationFeedbackHandler.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/DefaultAuthenticationFeedbackHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/DefaultAuthenticationFeedbackHandler.java?rev=905248&view=auto
==============================================================================
--- sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/DefaultAuthenticationFeedbackHandler.java (added)
+++ sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/DefaultAuthenticationFeedbackHandler.java Mon Feb  1 10:57:43 2010
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.commons.auth.spi;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.commons.auth.AuthenticationSupport;
+import org.slf4j.LoggerFactory;
+
+public class DefaultAuthenticationFeedbackHandler implements
+        AuthenticationFeedbackHandler {
+
+    /**
+     * Handles an optional request for a redirect after successful
+     * authentication and <code>true</code> if the request has been redirected.
+     * <p>
+     * If sending the redirect response fails due to some IO problems, the
+     * request is still terminated but an error message is logged indicating the
+     * problem.
+     *
+     * @return <code>true</code> if redirect was requested. Otherwise
+     *         <code>false</code> is returned. Note, that <code>true</code> is
+     *         returned regardless of whether sending the redirect response
+     *         succeeded or not.
+     */
+    public static boolean handleRedirect(final HttpServletRequest request,
+            final HttpServletResponse response) {
+
+        final String redirect = request.getParameter(AuthenticationSupport.REDIRECT_PARAMETER);
+        if (redirect != null) {
+
+            // find the redirect target
+            final String target;
+            if ("true".equalsIgnoreCase(redirect) || redirect.length() == 0) {
+                // redirect to the same path
+                target = request.getRequestURI();
+
+            } else if (redirect.startsWith("/")) {
+                // absolute target (in the servlet context)
+                target = request.getContextPath() + redirect;
+
+            } else {
+                // redirect relative to the current request
+                target = redirect;
+
+            }
+
+            // and redirect ensuring the response is sent to the client
+            try {
+                response.sendRedirect(target);
+            } catch (Exception e) {
+                // expected: IOException and IllegalStateException
+                LoggerFactory.getLogger(
+                    DefaultAuthenticationFeedbackHandler.class).error(
+                    "handleRedirect: Failed to send redirect to " + target
+                        + ", aborting request without redirect", e);
+            }
+
+            // consider the request done
+            return true;
+        }
+
+        // no redirect requested
+        return false;
+    }
+
+    /**
+     * This default implementation does nothing.
+     * <p>
+     * Extensions of this class may overwrite to cleanup any internal state.
+     */
+    public void authenticationFailed(HttpServletRequest request,
+            HttpServletResponse response, AuthenticationInfo authInfo) {
+    }
+
+    /**
+     * This default implementation calls the
+     * {@link #handleRedirect(HttpServletRequest, HttpServletResponse)} method
+     * to optionally redirect the request after successful authentication.
+     * <p>
+     * Extensions of this class may overwrite this method to perform additional
+     * cleanup etc.
+     *
+     * @param the result of calling the
+     *            {@link #handleRedirect(HttpServletRequest, HttpServletResponse)}
+     *            method.
+     */
+    public boolean authenticationSucceeded(HttpServletRequest request,
+            HttpServletResponse response, AuthenticationInfo authInfo) {
+        return handleRedirect(request, response);
+    }
+
+}

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/DefaultAuthenticationFeedbackHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/commons/auth/src/main/java/org/apache/sling/commons/auth/spi/DefaultAuthenticationFeedbackHandler.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url