incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fmesc...@apache.org
Subject svn commit: r886796 - in /sling/trunk/bundles/extensions/httpauth/src/main: java/org/apache/sling/httpauth/impl/AuthorizationHeaderAuthenticationHandler.java resources/org/apache/sling/httpauth/impl/LoginFormTemplate.html
Date Thu, 03 Dec 2009 14:36:38 GMT
Author: fmeschbe
Date: Thu Dec  3 14:36:37 2009
New Revision: 886796

URL: http://svn.apache.org/viewvc?rev=886796&view=rev
Log:
SLING-1220 Fix interaction between authentication handler and login form to convey invalid
credentials with a 403 status code instead of just resending the login form with a status
code of 200. Further fixes included:
   * only send login request once (duplicate reference in the form)
   * properly identify logged-in request (don't use AuthType since there
     is at least one servlet container, which returns a non-null value
     even if the servlet container does not authenticate the request)

Modified:
    sling/trunk/bundles/extensions/httpauth/src/main/java/org/apache/sling/httpauth/impl/AuthorizationHeaderAuthenticationHandler.java
    sling/trunk/bundles/extensions/httpauth/src/main/resources/org/apache/sling/httpauth/impl/LoginFormTemplate.html

Modified: sling/trunk/bundles/extensions/httpauth/src/main/java/org/apache/sling/httpauth/impl/AuthorizationHeaderAuthenticationHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/httpauth/src/main/java/org/apache/sling/httpauth/impl/AuthorizationHeaderAuthenticationHandler.java?rev=886796&r1=886795&r2=886796&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/httpauth/src/main/java/org/apache/sling/httpauth/impl/AuthorizationHeaderAuthenticationHandler.java
(original)
+++ sling/trunk/bundles/extensions/httpauth/src/main/java/org/apache/sling/httpauth/impl/AuthorizationHeaderAuthenticationHandler.java
Thu Dec  3 14:36:37 2009
@@ -32,6 +32,7 @@
 import org.apache.sling.engine.auth.AuthenticationHandler;
 import org.apache.sling.engine.auth.AuthenticationInfo;
 import org.osgi.service.component.ComponentContext;
+import org.osgi.service.http.HttpContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -40,7 +41,7 @@
  * the authorization steps based on the Authorization header of the HTTP
  * request. This authenticator should eventually support both BASIC and DIGEST
  * authentication methods.
- * 
+ *
  * @scr.component immediate="false" label="%auth.http.name"
  *                description="%auth.http.description"
  * @scr.property name="service.description"
@@ -62,7 +63,7 @@
      * in the {@link #authenticate(HttpServletRequest, HttpServletResponse)}
      * method if no credentials are present in the request (value is
      * "sling:authRequestLogin").
-     * 
+     *
      * @see #authenticate(HttpServletRequest, HttpServletResponse)
      */
     static final String REQUEST_LOGIN_PARAMETER = "sling:authRequestLogin";
@@ -131,7 +132,7 @@
      * the request may be for an included servlet, in which case the values for
      * some URI specific values are contained in javax.servlet.include.* request
      * attributes.
-     * 
+     *
      * @param request The request object containing the information for the
      *            authentication.
      * @param response The response object which may be used to send the
@@ -162,7 +163,7 @@
 
     /**
      * Sends back the form to log into the system.
-     * 
+     *
      * @param request The request object
      * @param response The response object to which to send the request
      * @return <code>true</code> is always returned by this handler
@@ -176,30 +177,55 @@
 
             // reset the response
             response.reset();
-            response.setStatus(HttpServletResponse.SC_OK);
+            response.setHeader("Cache-Control", "no-cache");
 
-            String form = getLoginForm();
+            if (isLoginRequested(request)) {
 
-            if (form != null) {
-
-                form = replaceVariables(form, "@@contextPath@@",
-                    request.getContextPath(), "/");
-                form = replaceVariables(form, "@@authType@@",
-                    request.getAuthType(), "");
-                form = replaceVariables(form, "@@user@@",
-                    request.getRemoteUser(), "");
-
-                response.setContentType("text/html");
-                response.setCharacterEncoding("UTF-8");
-                response.getWriter().print(form);
+                // this is the ajax request for authentication which failed, we
+                // send back a 403/FORBIDDEN here to indicate failure
+                // Resoning:
+                //  - using 401 would technically be correct but the browsers
+                //    intercept these even for ajax requests. so sending 403
+                //    indicates wrong credentials but allows processing without
+                //    browser intervention
+                //  - setting status only instead of using sendError prevents
+                //    any error handling scripts from kicking in (and
+                //    potentially modifying the result)
+                response.setStatus(HttpServletResponse.SC_FORBIDDEN);
 
             } else {
-                
-                // have no form, so just send 401/UNATHORIZED for simple login
-                sendUnauthorized(response);
-                
+
+                response.setStatus(HttpServletResponse.SC_OK);
+
+                String form = getLoginForm();
+
+                if (form != null) {
+
+                    form = replaceVariables(
+                        form,
+                        "@@loggedIn@@",
+                        String.valueOf(request.getAttribute(HttpContext.AUTHENTICATION_TYPE)
!= null),
+                        "false");
+                    form = replaceVariables(form, "@@contextPath@@",
+                        request.getContextPath(), "/");
+                    form = replaceVariables(form, "@@authType@@",
+                        request.getAuthType(), "");
+                    form = replaceVariables(form, "@@user@@",
+                        request.getRemoteUser(), "");
+
+                    response.setContentType("text/html");
+                    response.setCharacterEncoding("UTF-8");
+                    response.getWriter().print(form);
+
+                } else {
+
+                    // have no form, so just send 401/UNATHORIZED for simple login
+                    sendUnauthorized(response);
+
+                }
+
             }
-            
+
         } else {
 
             log.error("requestAuthentication: Response is committed, cannot request authentication");
@@ -210,6 +236,14 @@
     }
 
     /**
+     * Returns true if the {@link #REQUEST_LOGIN_PARAMETER} parameter is set in
+     * the request.
+     */
+    private boolean isLoginRequested(HttpServletRequest request) {
+        return request.getParameter(REQUEST_LOGIN_PARAMETER) != null;
+    }
+
+    /**
      * If the {@link #REQUEST_LOGIN_PARAMETER} parameter is set this method
      * sends status <code>401</code> (Unauthorized) with a
      * <code>WWW-Authenticate</code> requesting standard HTTP header
@@ -220,7 +254,7 @@
      * <code>false</code> is returned if the request parameter is not set, if
      * the response is already committed or if an error occurred sending the
      * status response. The latter two situations are logged as errors.
-     * 
+     *
      * @param request The request object
      * @param response The response object to which to send the request
      * @return <code>true</code> if the 401/UNAUTHORIZED method has successfully
@@ -232,7 +266,7 @@
         // presume 401/UNAUTHORIZED has not been sent
         boolean authenticationForced = false;
 
-        if (request.getParameter(REQUEST_LOGIN_PARAMETER) != null) {
+        if (isLoginRequested(request)) {
 
             if (!response.isCommitted()) {
 
@@ -243,25 +277,25 @@
                 log.error("forceAuthentication: Response is committed, cannot request authentication");
 
             }
-            
+
         } else {
-            
+
             log.debug(
                 "forceAuthentication: Not forcing authentication because request parameter
{} is not set",
                 REQUEST_LOGIN_PARAMETER);
-            
+
         }
 
         // true if 401/UNAUTHORIZED has been sent, false otherwise
         return authenticationForced;
     }
-    
+
     /**
      * Sends status <code>401</code> (Unauthorized) with a
      * <code>WWW-Authenticate</code> requesting standard HTTP header
      * authentication with the <code>Basic</code> scheme and the configured
      * realm name.
-     * 
+     *
      * @param response The response object to which to send the request
      * @return <code>true</code> if the 401/UNAUTHORIZED method has successfully
      *         been sent.
@@ -406,12 +440,12 @@
                     }
 
                 }
-                
+
             } else {
-                
+
                 log.error("getLoginForm: Cannot access login form template at "
                     + LOGIN_FORM_TEMPLATE);
-                
+
             }
         }
 
@@ -422,7 +456,7 @@
      * Replaces all occurrences in the <code>template</code> of the
      * <code>key</code> (a regular expression) by the <code>value</code>
or
      * <code>defaultValue</code>.
-     * 
+     *
      * @param template The template to replace occurences of key
      * @param key The regular expression of the key to replace
      * @param value The replacement value

Modified: sling/trunk/bundles/extensions/httpauth/src/main/resources/org/apache/sling/httpauth/impl/LoginFormTemplate.html
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/httpauth/src/main/resources/org/apache/sling/httpauth/impl/LoginFormTemplate.html?rev=886796&r1=886795&r2=886796&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/httpauth/src/main/resources/org/apache/sling/httpauth/impl/LoginFormTemplate.html
(original)
+++ sling/trunk/bundles/extensions/httpauth/src/main/resources/org/apache/sling/httpauth/impl/LoginFormTemplate.html
Thu Dec  3 14:36:37 2009
@@ -58,7 +58,7 @@
 <script>
   // fix the display of login/logout
   function onLoad() {
-      if ('@@authType@@') {
+      if (@@loggedIn@@) {
           document.getElementById("logout").style.display = "block";
       } else {
           document.getElementById("login").style.display = "block";
@@ -99,15 +99,24 @@
         xmlhttp.abort();
       }
 
+      // send a synchronous request
       xmlhttp.open('POST', '@@contextPath@@?sling:authRequestLogin=1', false, user, pass);
       xmlhttp.send('');
+
+      // success if everything went smoothly      
+      return xmlhttp.status == 200;
   }
-          
+   
   function loginuser() {
     var user = document.forms['login'].usr.value;
     var pass = document.forms['login'].pwd.value;
-    sendRequest(user, pass);
-    document.location = document.location
+    if (sendRequest(user, pass)) {
+        document.location = document.location;
+    } else {
+        alert("Wrong user name or password. Try again!");
+        sendRequest('__failed_login_user__', 'null');
+    }
+
     return false;
   }
 
@@ -122,7 +131,7 @@
           document.execCommand('ClearAuthenticationCache');
   
       } catch (e) {
-          sendRequest('__forced_logout_user__', 'null');
+        sendRequest('__forced_logout_user__', 'null');
       }
   
       document.location = document.location
@@ -148,7 +157,7 @@
   </tr>
   <tr>
     <td colspan='2' align='center'><input type='submit'
-      value='Login' onClick='loginuser();' /></td>
+      value='Login' /></td>
   </tr>
 </table>
 </form>



Mime
View raw message