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/09/13 12:08:53 UTC

svn commit: r996477 - in /sling/trunk/bundles/auth: core/src/main/java/org/apache/sling/auth/core/impl/ core/src/main/java/org/apache/sling/auth/core/spi/ form/ form/src/main/java/org/apache/sling/auth/form/impl/ openid/ selector/ selector/src/main/jav...

Author: fmeschbe
Date: Mon Sep 13 10:08:52 2010
New Revision: 996477

URL: http://svn.apache.org/viewvc?rev=996477&view=rev
Log:
SLING-1752 Unify resource attribute/parameter setting and default value handling

Modified:
    sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/HttpBasicAuthenticationHandler.java
    sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/LoginServlet.java
    sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/LogoutServlet.java
    sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/SlingAuthenticator.java
    sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/spi/AbstractAuthenticationHandler.java
    sling/trunk/bundles/auth/form/pom.xml
    sling/trunk/bundles/auth/form/src/main/java/org/apache/sling/auth/form/impl/FormAuthenticationHandler.java
    sling/trunk/bundles/auth/openid/pom.xml
    sling/trunk/bundles/auth/selector/pom.xml
    sling/trunk/bundles/auth/selector/src/main/java/org/apache/sling/auth/selector/SelectorAuthenticationHandler.java

Modified: sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/HttpBasicAuthenticationHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/HttpBasicAuthenticationHandler.java?rev=996477&r1=996476&r2=996477&view=diff
==============================================================================
--- sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/HttpBasicAuthenticationHandler.java (original)
+++ sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/HttpBasicAuthenticationHandler.java Mon Sep 13 10:08:52 2010
@@ -234,6 +234,17 @@ class HttpBasicAuthenticationHandler ext
 
             response.resetBuffer();
 
+            /*
+             * TODO: Check whether we have to redirect
+             * If this is a GET request not targeted at the registration path
+             * for which this handler is selected we have to redirect to the
+             * registration path using either the provided resource attribute
+             * or parameter or the current URL as the "resource" parameter
+             * for the redirect and also setting the "sling:authRequestLogin"
+             * parameter to "BASIC" to get the 401 response for the registration
+             * path and redirect back to actual path afterwards.
+             */
+
             // just set the status because this may be called as part of an
             // error handler in which case sendError would result in an error
             // handler loop and thus be ignored.

Modified: sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/LoginServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/LoginServlet.java?rev=996477&r1=996476&r2=996477&view=diff
==============================================================================
--- sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/LoginServlet.java (original)
+++ sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/LoginServlet.java Mon Sep 13 10:08:52 2010
@@ -35,6 +35,7 @@ import org.apache.sling.api.SlingHttpSer
 import org.apache.sling.api.auth.Authenticator;
 import org.apache.sling.api.auth.NoAuthenticationHandlerException;
 import org.apache.sling.api.servlets.SlingAllMethodsServlet;
+import org.apache.sling.auth.core.spi.AbstractAuthenticationHandler;
 import org.osgi.framework.Constants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -70,7 +71,6 @@ public class LoginServlet extends SlingA
     protected void service(SlingHttpServletRequest request,
             SlingHttpServletResponse response) throws IOException {
 
-        final String resourcePath = request.getParameter(Authenticator.LOGIN_RESOURCE);
 
         // if the request is logged in and the resource is not set (such
         // as when requesting /system/sling/login from the browser with the
@@ -79,6 +79,8 @@ public class LoginServlet extends SlingA
         // through the login servlet), redirect to root now assuming we are
         // authenticated.
         if (request.getAuthType() != null) {
+            final String resourcePath = AbstractAuthenticationHandler.getLoginResource(
+                request, null);
             if (isSelf(resourcePath)) {
                 String redirectTarget = request.getContextPath() + "/";
                 log.warn(
@@ -94,8 +96,8 @@ public class LoginServlet extends SlingA
             try {
 
                 // set the login resource to select the authenticator
-                request.setAttribute(Authenticator.LOGIN_RESOURCE,
-                    (resourcePath != null) ? resourcePath : "/");
+                AbstractAuthenticationHandler.setLoginResourceAttribute(
+                    request, request.getContextPath());
                 authenticator.login(request, response);
                 return;
 

Modified: sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/LogoutServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/LogoutServlet.java?rev=996477&r1=996476&r2=996477&view=diff
==============================================================================
--- sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/LogoutServlet.java (original)
+++ sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/LogoutServlet.java Mon Sep 13 10:08:52 2010
@@ -32,6 +32,7 @@ import org.apache.sling.api.SlingHttpSer
 import org.apache.sling.api.SlingHttpServletResponse;
 import org.apache.sling.api.auth.Authenticator;
 import org.apache.sling.api.servlets.SlingAllMethodsServlet;
+import org.apache.sling.auth.core.spi.AbstractAuthenticationHandler;
 import org.osgi.framework.Constants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -70,10 +71,8 @@ public class LogoutServlet extends Sling
         final Authenticator authenticator = this.authenticator;
         if (authenticator != null) {
             try {
-                final String resourcePath = request.getParameter("resource");
-                request.setAttribute(Authenticator.LOGIN_RESOURCE,
-                    (resourcePath != null) ? resourcePath : "/");
-
+                AbstractAuthenticationHandler.setLoginResourceAttribute(
+                    request, request.getContextPath());
                 authenticator.logout(request, response);
                 return;
             } catch (IllegalStateException ise) {

Modified: sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/SlingAuthenticator.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/SlingAuthenticator.java?rev=996477&r1=996476&r2=996477&view=diff
==============================================================================
--- sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/SlingAuthenticator.java (original)
+++ sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/impl/SlingAuthenticator.java Mon Sep 13 10:08:52 2010
@@ -379,9 +379,8 @@ public class SlingAuthenticator implemen
             } else if (authInfo == AuthenticationInfo.FAIL_AUTH) {
 
                 log.debug("handleSecurity: Credentials present but not valid, request authentication again");
-                request.setAttribute(LOGIN_RESOURCE,
-                    AbstractAuthenticationHandler.getLoginResource(request,
-                        request.getRequestURI()));
+                AbstractAuthenticationHandler.setLoginResourceAttribute(
+                    request, request.getRequestURI());
                 doLogin(request, response);
                 return false;
 
@@ -1042,12 +1041,21 @@ public class SlingAuthenticator implemen
      */
     private String getHandlerSelectionPath(HttpServletRequest request) {
         final Object loginPathO = request.getAttribute(Authenticator.LOGIN_RESOURCE);
-        String path = (loginPathO instanceof String)
-                ? (String) loginPathO
-                : request.getPathInfo();
+        String path;
+        if (loginPathO instanceof String) {
+            path = (String) loginPathO;
+            final String ctxPath = request.getContextPath();
+            if (ctxPath !=  null && path.startsWith(ctxPath)) {
+                path = path.substring(ctxPath.length());
+            }
+        } else {
+            path = request.getPathInfo();
+        }
+
         if (path == null || path.length() == 0) {
             path = "/";
         }
+
         return path;
     }
 
@@ -1071,18 +1079,14 @@ public class SlingAuthenticator implemen
             return;
         }
 
-        // check resource attribute/parameter
-        String target = (String) request.getAttribute(LOGIN_RESOURCE);
-        if (target == null || target.length() == 0) {
-            target = request.getParameter(LOGIN_RESOURCE);
-            if (target == null || target.length() == 0) {
-                target = "/";
-            }
-        }
+        // find the redirect target from the resource attribute or parameter
+        // falling back to the reuest context path (or /) if not set
+        final String target = AbstractAuthenticationHandler.setLoginResourceAttribute(
+            request, request.getContextPath());
 
         // redirect to there
         try {
-            response.sendRedirect(request.getContextPath() + target);
+            response.sendRedirect(target);
         } catch (IOException e) {
             log.error("Failed to redirect to the page: " + target, e);
         }

Modified: sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/spi/AbstractAuthenticationHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/spi/AbstractAuthenticationHandler.java?rev=996477&r1=996476&r2=996477&view=diff
==============================================================================
--- sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/spi/AbstractAuthenticationHandler.java (original)
+++ sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core/spi/AbstractAuthenticationHandler.java Mon Sep 13 10:08:52 2010
@@ -52,9 +52,9 @@ public abstract class AbstractAuthentica
             final HttpServletRequest request, final String name,
             final String defaultValue) {
 
-        Object resObj = request.getAttribute(name);
-        if ((resObj instanceof String) && ((String) resObj).length() > 0) {
-            return (String) resObj;
+        final String resourceAttr = getAttributeString(request, name);
+        if (resourceAttr != null) {
+            return resourceAttr;
         }
 
         final String resource = request.getParameter(name);
@@ -83,4 +83,59 @@ public abstract class AbstractAuthentica
         return getAttributeOrParameter(request, Authenticator.LOGIN_RESOURCE,
             defaultLoginResource);
     }
+
+    /**
+     * Ensures and returns the {@link Authenticator#LOGIN_RESOURCE} request
+     * attribute is set to a non-null, non-empty string. If the attribute is not
+     * currently set, this method sets it as follows:
+     * <ol>
+     * <li>If the {@link Authenticator#LOGIN_RESOURCE} request parameter is set
+     * to a non-empty string, that parameter is set</li>
+     * <li>Otherwise if the <code>defaultValue</code> is a non-empty string the
+     * default value is used</li>
+     * <li>Otherwise the attribute is set to "/"</li>
+     * </ol>
+     *
+     * @param request The request to check for the resource attribute
+     * @param defaultValue The default value to use if the attribute is not set
+     *            and the request parameter is not set. This parameter is
+     *            ignored if it is <code>null</code> or an empty string.
+     * @return returns the value of resource request attribute
+     */
+    public static String setLoginResourceAttribute(
+            final HttpServletRequest request, final String defaultValue) {
+        String resourceAttr = getAttributeString(request,
+            Authenticator.LOGIN_RESOURCE);
+        if (resourceAttr == null) {
+            final String resourcePar = request.getParameter(Authenticator.LOGIN_RESOURCE);
+            if (resourcePar != null && resourcePar.length() > 0) {
+                resourceAttr = resourcePar;
+            } else if (defaultValue != null && defaultValue.length() > 0) {
+                resourceAttr = defaultValue;
+            } else {
+                resourceAttr = "/";
+            }
+            request.setAttribute(Authenticator.LOGIN_RESOURCE, resourceAttr);
+        }
+        return resourceAttr;
+    }
+
+    /**
+     * Returns the name request attribute if it is a non-empty string value.
+     *
+     * @param request The request from which to retrieve the attribute
+     * @param name The name of the attribute to return
+     * @return The named request attribute or <code>null</code> if the attribute
+     *         is not set or is not a non-empty string value.
+     */
+    private static String getAttributeString(final HttpServletRequest request,
+            final String name) {
+        Object resObj = request.getAttribute(name);
+        if ((resObj instanceof String) && ((String) resObj).length() > 0) {
+            return (String) resObj;
+        }
+
+        // not set or not a non-empty string
+        return null;
+    }
 }

Modified: sling/trunk/bundles/auth/form/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/auth/form/pom.xml?rev=996477&r1=996476&r2=996477&view=diff
==============================================================================
--- sling/trunk/bundles/auth/form/pom.xml (original)
+++ sling/trunk/bundles/auth/form/pom.xml Mon Sep 13 10:08:52 2010
@@ -98,7 +98,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.auth.core</artifactId>
-            <version>1.0.0</version>
+            <version>1.0.3-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>

Modified: sling/trunk/bundles/auth/form/src/main/java/org/apache/sling/auth/form/impl/FormAuthenticationHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/auth/form/src/main/java/org/apache/sling/auth/form/impl/FormAuthenticationHandler.java?rev=996477&r1=996476&r2=996477&view=diff
==============================================================================
--- sling/trunk/bundles/auth/form/src/main/java/org/apache/sling/auth/form/impl/FormAuthenticationHandler.java (original)
+++ sling/trunk/bundles/auth/form/src/main/java/org/apache/sling/auth/form/impl/FormAuthenticationHandler.java Mon Sep 13 10:08:52 2010
@@ -330,13 +330,26 @@ public class FormAuthenticationHandler e
             if (authData != null) {
                 if (tokenStore.isValid(authData)) {
                     info = createAuthInfo(authData);
+                } else if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
+                    // signal to AJAX the request is forbidden
+                    try {
+                        response.sendError(
+                            HttpServletResponse.SC_REQUEST_TIMEOUT,
+                            "Session Timeout, please login");
+                        response.flushBuffer();
+                    } catch (IOException ioe) {
+                        // TODO: log !!
+                    }
+                    return AuthenticationInfo.DOING_AUTH;
                 } else {
                     if (this.loginAfterExpire) {
-                      // signal the requestCredentials method a previous login failure
-                      request.setAttribute(PAR_J_REASON, FormReason.TIMEOUT);
-                      info = AuthenticationInfo.FAIL_AUTH;
+                        // signal the requestCredentials method a previous login
+                        // failure
+                        request.setAttribute(PAR_J_REASON, FormReason.TIMEOUT);
+                        info = AuthenticationInfo.FAIL_AUTH;
                     }
-                    // clear the cookie, its invalid and we should get rid of it so that the invalid cookie
+                    // clear the cookie, its invalid and we should get rid of it
+                    // so that the invalid cookie
                     // isn't present on the authN operation.
                     authStorage.clear(request, response);
                 }
@@ -379,11 +392,8 @@ public class FormAuthenticationHandler e
             return true;
         }
 
-        String resource = getLoginResource(request, null);
-        if (resource == null) {
-            resource = request.getContextPath() + request.getPathInfo();
-            request.setAttribute(Authenticator.LOGIN_RESOURCE, resource);
-        }
+        final String resource = setLoginResourceAttribute(request,
+            request.getRequestURI());
 
         if (includeLoginForm && (resourceResolverFactory != null)) {
             ResourceResolver resourceResolver = null;
@@ -651,9 +661,7 @@ public class FormAuthenticationHandler e
                 // authentication, otherwise the request may be processed
                 // as a POST request to the j_security_check page (unless
                 // the j_validate parameter is set)
-                if (getLoginResource(request, null) == null) {
-                    request.setAttribute(Authenticator.LOGIN_RESOURCE, "/");
-                }
+                setLoginResourceAttribute(request, request.getContextPath());
             }
         }
 
@@ -896,6 +904,15 @@ public class FormAuthenticationHandler e
      * {@link CookieAuthData} in an HTTP Cookie.
      */
     private static class CookieStorage implements AuthenticationStorage {
+
+        /**
+         * The Set-Cookie header used to manage the login cookie.
+         *
+         * @see CookieStorage#setCookie(HttpServletRequest, HttpServletResponse,
+         *      String, String, int, String)
+         */
+        private static final String HEADER_SET_COOKIE = "Set-Cookie";
+
         private final String cookieName;
         private final String domainCookieName;
         private final String defaultCookieDomain;
@@ -917,8 +934,11 @@ public class FormAuthenticationHandler e
 
                         // reverse the base64 encoding
                         try {
-                            return new String(Base64.decodeBase64(value),
-                                "UTF-8");
+                            String result = new String(
+                                Base64.decodeBase64(value), "UTF-8");
+                            if (result.length() > 0) {
+                                return result;
+                            }
                         } catch (UnsupportedEncodingException e1) {
                             throw new RuntimeException(e1);
                         }
@@ -988,14 +1008,37 @@ public class FormAuthenticationHandler e
                     ? "/"
                     : ctxPath;
 
-            Cookie cookie = new Cookie(name, value);
+            /*
+             * The Servlet Spec 2.5 does not allow us to set the commonly used
+             * HttpOnly attribute on cookies (Servlet API 3.0 does) so we create
+             * the Set-Cookie header manually. See
+             * http://www.owasp.org/index.php/HttpOnly for information on what
+             * the HttpOnly attribute is used for.
+             */
+
+            final StringBuilder header = new StringBuilder();
+
+            // default setup with name, value, cookie path and HttpOnly
+            header.append(name).append('=').append(value);
+            header.append(";Path=").append(cookiePath);
+            header.append(";HttpOnly"); // don't allow JS access
+
+            // set the cookie domain if so configured
             if (domain != null) {
-                cookie.setDomain(domain);
+                header.append(";Domain=").append(domain);
+            }
+
+            // Only set the Max-Age attribute to remove the cookie
+            if (age == 0) {
+                header.append(";Max-Age=").append(age);
             }
-            cookie.setMaxAge(age);
-            cookie.setPath(cookiePath);
-            cookie.setSecure(request.isSecure());
-            response.addCookie(cookie);
+
+            // ensure the cookie is secured if this is an https request
+            if (request.isSecure()) {
+                header.append(";Secure");
+            }
+
+            response.addHeader(HEADER_SET_COOKIE, header.toString());
         }
     }
 

Modified: sling/trunk/bundles/auth/openid/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/auth/openid/pom.xml?rev=996477&r1=996476&r2=996477&view=diff
==============================================================================
--- sling/trunk/bundles/auth/openid/pom.xml (original)
+++ sling/trunk/bundles/auth/openid/pom.xml Mon Sep 13 10:08:52 2010
@@ -107,7 +107,7 @@
 		<dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.auth.core</artifactId>
-            <version>1.0.0</version>
+            <version>1.0.3-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
 		<dependency>

Modified: sling/trunk/bundles/auth/selector/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/auth/selector/pom.xml?rev=996477&r1=996476&r2=996477&view=diff
==============================================================================
--- sling/trunk/bundles/auth/selector/pom.xml (original)
+++ sling/trunk/bundles/auth/selector/pom.xml Mon Sep 13 10:08:52 2010
@@ -100,7 +100,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.auth.core</artifactId>
-            <version>1.0.0</version>
+            <version>1.0.3-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>

Modified: sling/trunk/bundles/auth/selector/src/main/java/org/apache/sling/auth/selector/SelectorAuthenticationHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/auth/selector/src/main/java/org/apache/sling/auth/selector/SelectorAuthenticationHandler.java?rev=996477&r1=996476&r2=996477&view=diff
==============================================================================
--- sling/trunk/bundles/auth/selector/src/main/java/org/apache/sling/auth/selector/SelectorAuthenticationHandler.java (original)
+++ sling/trunk/bundles/auth/selector/src/main/java/org/apache/sling/auth/selector/SelectorAuthenticationHandler.java Mon Sep 13 10:08:52 2010
@@ -96,54 +96,42 @@ public class SelectorAuthenticationHandl
 
     public boolean requestCredentials(HttpServletRequest request,
             HttpServletResponse response) throws IOException {
-        String resource = getLoginResource(request, null);
-        if (resource == null) {
-            resource = request.getContextPath() + request.getPathInfo();
-            request.setAttribute(Authenticator.LOGIN_RESOURCE, resource);
-        }
 
         // prepare the login form redirection target
         final StringBuilder targetBuilder = new StringBuilder();
         targetBuilder.append(request.getContextPath());
         targetBuilder.append(loginForm);
 
-        // append originally requested resource (for redirect after login)
-        char parSep = '?';
-
-        if (resource != null) {
-            targetBuilder.append(parSep).append(Authenticator.LOGIN_RESOURCE);
-            targetBuilder.append("=").append(
-                URLEncoder.encode(resource, "UTF-8"));
-            parSep = '&';
-        }
+        targetBuilder.append('?').append(Authenticator.LOGIN_RESOURCE);
+        targetBuilder.append("=").append(
+            URLEncoder.encode(
+                setLoginResourceAttribute(request, request.getRequestURI()),
+                "UTF-8"));
 
         // append indication of previous login failure
         if (request.getAttribute(PAR_J_REASON) != null) {
             final Object jReason = request.getAttribute(PAR_J_REASON);
-            @SuppressWarnings("unchecked")
+            @SuppressWarnings("rawtypes")
             final String reason = (jReason instanceof Enum)
                     ? ((Enum) jReason).name()
                     : jReason.toString();
-            targetBuilder.append(parSep).append(PAR_J_REASON);
+            targetBuilder.append('&').append(PAR_J_REASON);
             targetBuilder.append("=").append(URLEncoder.encode(reason, "UTF-8"));
-            parSep = '&';
         } else if (request.getAttribute(OpenIDConstants.OPENID_FAILURE_REASON) != null) {
             final Object jReason = request.getAttribute(OpenIDConstants.OPENID_FAILURE_REASON);
-            @SuppressWarnings("unchecked")
+            @SuppressWarnings("rawtypes")
             final String reason = (jReason instanceof Enum)
                     ? ((Enum) jReason).name()
                     : jReason.toString();
-            targetBuilder.append(parSep).append(PAR_J_REASON);
+            targetBuilder.append('&').append(PAR_J_REASON);
             targetBuilder.append("=").append(URLEncoder.encode(reason, "UTF-8"));
-            parSep = '&';
         }
 
         // append selected authentication type of previous request
         if (request.getParameter(PAR_SELECTED_AUTH_TYPE) != null) {
-            targetBuilder.append(parSep).append(PAR_SELECTED_AUTH_TYPE);
+            targetBuilder.append('&').append(PAR_SELECTED_AUTH_TYPE);
             targetBuilder.append("=").append(
                 request.getParameter(PAR_SELECTED_AUTH_TYPE));
-            parSep = '&';
         }
 
         // finally redirect to the login form