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 2009/02/08 23:00:06 UTC

svn commit: r742179 - /incubator/sling/trunk/engine/src/main/java/org/apache/sling/engine/impl/auth/SlingAuthenticator.java

Author: fmeschbe
Date: Sun Feb  8 22:00:05 2009
New Revision: 742179

URL: http://svn.apache.org/viewvc?rev=742179&view=rev
Log:
SLING-849 Apply patch by Rory Douglas (thanks) allowing
for per-virtual host authentication handlers

Modified:
    incubator/sling/trunk/engine/src/main/java/org/apache/sling/engine/impl/auth/SlingAuthenticator.java

Modified: incubator/sling/trunk/engine/src/main/java/org/apache/sling/engine/impl/auth/SlingAuthenticator.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/engine/src/main/java/org/apache/sling/engine/impl/auth/SlingAuthenticator.java?rev=742179&r1=742178&r2=742179&view=diff
==============================================================================
--- incubator/sling/trunk/engine/src/main/java/org/apache/sling/engine/impl/auth/SlingAuthenticator.java (original)
+++ incubator/sling/trunk/engine/src/main/java/org/apache/sling/engine/impl/auth/SlingAuthenticator.java Sun Feb  8 22:00:05 2009
@@ -20,11 +20,13 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.Dictionary;
+import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.List;
+import java.util.Map;
 
 import javax.jcr.Credentials;
 import javax.jcr.LoginException;
@@ -117,7 +119,7 @@
 
     private int authHandlerTrackerCount;
 
-    private AuthenticationHandlerInfo[] authHandlerCache;
+    private Map<String, Map<String, AuthenticationHandlerInfo[]>> authHandlerCache;
 
     /** The name of the impersonation parameter */
     private String sudoParameterName;
@@ -252,7 +254,7 @@
     public void requestAuthentication(HttpServletRequest request,
             HttpServletResponse response) {
 
-        AuthenticationHandlerInfo[] handlerInfos = getAuthenticationHandlers();
+        AuthenticationHandlerInfo[] handlerInfos = findApplicableAuthenticationHandlers(request);
         boolean done = false;
         for (int i = 0; !done && i < handlerInfos.length; i++) {
             if ( request.getPathInfo().startsWith(handlerInfos[i].path) ) {
@@ -274,8 +276,8 @@
         if ( !done ) {
             // no handler could send an authentication request, fail with FORBIDDEN
             log.info(
-            		"requestAuthentication: No handler for request, sending FORBIDDEN ({} handlers available)",
-            		handlerInfos.length
+                    "requestAuthentication: No handler for request, sending FORBIDDEN ({} handlers available)",
+                    handlerInfos.length
             );
             sendFailure(response);
         }
@@ -330,32 +332,121 @@
         return repo;
     }
 
+    private static Map<String,Map<String, AuthenticationHandlerInfo[]>> EMPTY_PROTOCOL_MAP = new HashMap<String, Map<String,AuthenticationHandlerInfo[]>>();
     private static AuthenticationHandlerInfo[] EMPTY_INFO = new AuthenticationHandlerInfo[0];
-    private AuthenticationHandlerInfo[] getAuthenticationHandlers() {
+    
+    private AuthenticationHandlerInfo[] findApplicableAuthenticationHandlers(HttpServletRequest request) {
+         Map<String, Map<String, AuthenticationHandlerInfo[]>> byProtocolMap = getAuthenticationHandlers();
+         
+         Map<String, AuthenticationHandlerInfo[]> byHostMap = byProtocolMap.get(request.getScheme());
+         if(byHostMap == null) {
+            byHostMap = byProtocolMap.get("");
+         }
+         
+         String hostname = request.getServerName() + 
+            (request.getServerPort() != 80 && request.getServerPort() != 443 ? ":" + request.getServerPort() : "");
+         
+         AuthenticationHandlerInfo[] infos = byHostMap.get(hostname);
+         if(infos == null) {
+             infos = byHostMap.get("");
+         }
+         
+         if(infos != null) {
+             return infos;
+         }
+         
+         return EMPTY_INFO;
+    }
+    
+    private Map<String, Map<String, AuthenticationHandlerInfo[]>> getAuthenticationHandlers() {
         if (authHandlerCache == null
             || authHandlerTrackerCount < authHandlerTracker.getTrackingCount()) {
             final ServiceReference[] services = authHandlerTracker.getServiceReferences();
             if ( services == null || services.length == 0 ) {
-                this.authHandlerCache = EMPTY_INFO;
+                this.authHandlerCache = EMPTY_PROTOCOL_MAP;
             } else {
-                final List<AuthenticationHandlerInfo> infos = new ArrayList<AuthenticationHandlerInfo>();
+                final Map<String, Map<String, List<AuthenticationHandlerInfo>>> byProtocolMap = new HashMap<String, Map<String,List<AuthenticationHandlerInfo>>>(); 
+                int regPathCount = 0;
+                
                 for (int i = 0; i < services.length; i++) {
                     final String paths[] = OsgiUtil.toStringArray(services[i].getProperty(AuthenticationHandler.PATH_PROPERTY));
+                    
                     if ( paths != null && paths.length > 0 ) {
                         final AuthenticationHandler handler = (AuthenticationHandler) authHandlerTracker.getService(services[i]);
+                        
                         for(int m = 0; m < paths.length; m++) {
                             if ( paths[m] != null && paths[m].length() > 0 ) {
-                                infos.add(new AuthenticationHandlerInfo(paths[m], handler));
+                                String path = paths[m];
+                                String host = "";
+                                String protocol = "";
+                                
+                                if(path.startsWith("http://") || path.startsWith("https://")) {
+                                    int idxProtocolEnd = path.indexOf("://");
+                                    protocol = path.substring(0,idxProtocolEnd);
+                                    path = path.substring(idxProtocolEnd + 1);
+                                }
+                                
+                                if (path.startsWith("//")) {
+                                    int idxHostEnd = path.indexOf("/",2);
+                                    idxHostEnd = idxHostEnd == -1 ? path.length() : idxHostEnd;
+                                    
+                                    if(path.length() > 2) {
+                                        host = path.substring(2,idxHostEnd);
+                                        if(idxHostEnd < path.length()) {
+                                            path = path.substring(idxHostEnd);
+                                        } else {
+                                            path="/";
+                                        }
+                                    } else {
+                                        path="/";
+                                    }
+                                } 
+                                
+                                AuthenticationHandlerInfo newInfo = new AuthenticationHandlerInfo(path, host, protocol, handler);
+                                
+                                Map<String, List<AuthenticationHandlerInfo>> byHostMap = byProtocolMap.get(protocol);
+                                if(byHostMap == null) {
+                                    byHostMap = new HashMap<String, List<AuthenticationHandlerInfo>>();
+                                    byProtocolMap.put(protocol, byHostMap);
+                                }
+                                
+                                List<AuthenticationHandlerInfo> byPathList = byHostMap.get(host);
+                                if(byPathList == null) {
+                                    byPathList = new ArrayList<AuthenticationHandlerInfo>();
+                                    byHostMap.put(host, byPathList);
+                                }
+                                
+                                byPathList.add(newInfo);
+                                regPathCount++;
                             }
                         }
                     }
                 }
-                if ( infos.size() == 0 ) {
-                    authHandlerCache = EMPTY_INFO;
+                if ( regPathCount == 0 ) {
+                    authHandlerCache = EMPTY_PROTOCOL_MAP;
                 } else {
-                    final AuthenticationHandlerInfo[] ac = infos.toArray(new AuthenticationHandlerInfo[infos.size()]);
-                    Arrays.sort(ac, AuthenticationHandlerInfoComparator.SINGLETON);
-                    authHandlerCache = ac;
+                    authHandlerCache = new HashMap<String, Map<String,AuthenticationHandlerInfo[]>>();
+                    
+                    for(Map.Entry<String, Map<String,List<AuthenticationHandlerInfo>>> protocolEntry : byProtocolMap.entrySet()) {
+                        Map<String,List<AuthenticationHandlerInfo>> hostMap = protocolEntry.getValue();
+                        
+                        Map<String, AuthenticationHandlerInfo[]> finalHostMap = authHandlerCache.get(protocolEntry.getKey());
+                        if(finalHostMap == null) {
+                            finalHostMap = new HashMap<String, AuthenticationHandlerInfo[]>();
+                            authHandlerCache.put(protocolEntry.getKey(), finalHostMap);
+                        }
+                        
+                        for(Map.Entry<String,List<AuthenticationHandlerInfo>> hostEntry : hostMap.entrySet()) {
+                            List<AuthenticationHandlerInfo> pathList = hostEntry.getValue();
+                            
+                            Collections.sort(pathList, AuthenticationHandlerInfoComparator.SINGLETON);
+                            
+                            final AuthenticationHandlerInfo[] authInfos = 
+                                pathList.toArray(new AuthenticationHandlerInfo[pathList.size()]);
+                            
+                            finalHostMap.put(hostEntry.getKey(), authInfos);
+                        }
+                    }
                 }
             }
             authHandlerTrackerCount = authHandlerTracker.getTrackingCount();
@@ -374,7 +465,7 @@
             pathInfo = "/";
         }
         
-        AuthenticationHandlerInfo[] local = getAuthenticationHandlers();
+        AuthenticationHandlerInfo[] local = findApplicableAuthenticationHandlers(request);
         for (int i = 0; i < local.length; i++) {
             if ( pathInfo.startsWith(local[i].path) ) {
                 final AuthenticationInfo authInfo = local[i].handler.authenticate(request,
@@ -384,7 +475,7 @@
                 }
             }
         }
-
+        
         // no handler found for the request ....
         log.debug("getCredentials: no handler could extract credentials");
         return null;
@@ -601,10 +692,14 @@
 
     protected static final class AuthenticationHandlerInfo {
         public final String path;
+        public final String host;
+        public final String protocol;
         public final AuthenticationHandler handler;
 
-        public AuthenticationHandlerInfo(final String p, final AuthenticationHandler h) {
+        public AuthenticationHandlerInfo(final String p, final String host, final String protocol, final AuthenticationHandler h) {
             this.path = p;
+            this.host = host;
+            this.protocol = protocol;
             this.handler = h;
         }
     }