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/10/11 13:35:16 UTC

svn commit: r1021309 - in /sling/trunk/bundles/auth/core/src/main/java/org/apache/sling/auth/core: impl/SlingAuthenticator.java spi/AbstractAuthenticationHandler.java

Author: fmeschbe
Date: Mon Oct 11 11:35:16 2010
New Revision: 1021309

URL: http://svn.apache.org/viewvc?rev=1021309&view=rev
Log:
SLING-1831 Recognize redirect loop by comparing the Referer header (if set) with the current request and only call the authentication handlers if no equal. Also provide a sensible default authentication failure reason as part of the handleLoginFailure method handling LoginException. Finally send back the authentication failure as response content (text/plain, UTF-8) in addition to setting it as the X-Reason response header.

Modified:
    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

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=1021309&r1=1021308&r2=1021309&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 Oct 11 11:35:16 2010
@@ -859,6 +859,10 @@ public class SlingAuthenticator implemen
                 reason.getMessage());
             log.debug("handleLoginFailure", reason);
 
+            // preset a reason for the login failure (if not done already)
+            ensureAttribute(request, AuthenticationHandler.FAILURE_REASON,
+                "User name and password do not match");
+
             doLogin(request, response);
 
         } else {
@@ -938,7 +942,7 @@ public class SlingAuthenticator implemen
         if (!AbstractAuthenticationHandler.isValidateRequest(request)) {
             if (isBrowserRequest(request)) {
 
-                if (!isAjaxRequest(request)) {
+                if (!isAjaxRequest(request) && !isLoginLoop(request)) {
                     try {
 
                         login(request, response);
@@ -982,10 +986,8 @@ public class SlingAuthenticator implemen
         // credential validation
 
         // ensure a failure reason
-        if (request.getAttribute(AuthenticationHandler.FAILURE_REASON) == null) {
-            request.setAttribute(AuthenticationHandler.FAILURE_REASON,
-                "Mandatory authentication is not possible");
-        }
+        ensureAttribute(request, AuthenticationHandler.FAILURE_REASON,
+            "Authentication Failed");
 
         AbstractAuthenticationHandler.sendInvalid(request, response);
     }
@@ -1018,6 +1020,45 @@ public class SlingAuthenticator implemen
     }
 
     /**
+     * Returns <code>true</code> if the current request was referred to by the
+     * same URL as the current request has. This is assumed to be caused by a
+     * loop in requesting credentials from the client. Such a loop will probably
+     * never cause the request for credentials to succeed, so it must be broken.
+     *
+     * @param request The request to check
+     * @return <code>true</code> if the request is considered to be a loop;
+     *         <code>false</code> otherwise
+     */
+    private boolean isLoginLoop(final HttpServletRequest request) {
+        String referer = request.getHeader("Referer");
+        if (referer != null) {
+            StringBuffer sb = request.getRequestURL();
+            if (request.getQueryString() != null) {
+                sb.append('?').append(request.getQueryString());
+            }
+            return referer.equals(sb.toString());
+        }
+
+        // no referer means no loop
+        return false;
+    }
+
+    /**
+     * Sets the name request attribute to the given value unless the request
+     * attribute is already set a non-<code>null</code> value.
+     *
+     * @param request The request on which to set the attribute
+     * @param attribute The name of the attribute to check/set
+     * @param value The value to set the attribute to if it is not already set
+     */
+    private void ensureAttribute(final HttpServletRequest request,
+            final String attribute, final Object value) {
+        if (request.getAttribute(attribute) == null) {
+            request.setAttribute(attribute, value);
+        }
+    }
+
+    /**
      * Sets the request attributes required by the OSGi HttpContext interface
      * specification for the <code>handleSecurity</code> method. In addition the
      * {@link SlingAuthenticator#REQUEST_ATTRIBUTE_RESOLVER} request attribute

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=1021309&r1=1021308&r2=1021309&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 Oct 11 11:35:16 2010
@@ -307,6 +307,9 @@ public abstract class AbstractAuthentica
             Object reason = request.getAttribute(AuthenticationHandler.FAILURE_REASON);
             if (reason != null) {
                 response.setHeader(X_REASON, reason.toString());
+                response.setContentType("text/plain");
+                response.setCharacterEncoding("UTF-8");
+                response.getWriter().println(reason);
             }
 
             response.flushBuffer();