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;
}
}