You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by rj...@apache.org on 2008/11/04 22:42:39 UTC
svn commit: r711422 -
/tomcat/trunk/java/org/apache/catalina/realm/JNDIRealm.java
Author: rjung
Date: Tue Nov 4 13:42:38 2008
New Revision: 711422
URL: http://svn.apache.org/viewvc?rev=711422&view=rev
Log:
Add ability to recursively search for roles
to JNDIRealm. That way nested groups work.
Modified:
tomcat/trunk/java/org/apache/catalina/realm/JNDIRealm.java
Modified: tomcat/trunk/java/org/apache/catalina/realm/JNDIRealm.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/realm/JNDIRealm.java?rev=711422&r1=711421&r2=711422&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/realm/JNDIRealm.java (original)
+++ tomcat/trunk/java/org/apache/catalina/realm/JNDIRealm.java Tue Nov 4 13:42:38 2008
@@ -22,9 +22,13 @@
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import javax.naming.Context;
import javax.naming.CommunicationException;
@@ -134,6 +138,14 @@
* in the user's element whose name is configured by the
* <code>userRoleName</code> property.</li>
*
+ * <li>A default role can be assigned to each user that was successfully
+ * authenticated by setting the <code>commonRole</code> property to the
+ * name of this role. The role doesn't have to exist in the directory.</li>
+ *
+ * <li>If the directory server contains nested roles, you can search for roles
+ * recursively by setting <code>roleRecursionLimit</code> to some positive value.
+ * The default value is <code>0</code>, so role searches do not recurse.</li>
+ *
* <li>Note that the standard <code><security-role-ref></code> element in
* the web application deployment descriptor allows applications to refer
* to roles programmatically by names other than those used in the
@@ -307,6 +319,13 @@
/**
+ * The maximum recursion depth when resolving roles recursively.
+ * By default we don't resolve roles recursively.
+ */
+ protected int roleRecursionLimit = 0;
+
+
+ /**
* The base element for role searches.
*/
protected String roleBase = "";
@@ -638,6 +657,28 @@
/**
+ * Return the maximum recursion depth for role searches.
+ */
+ public int getRoleRecursionLimit() {
+
+ return (this.roleRecursionLimit);
+
+ }
+
+
+ /**
+ * Set the maximum recursion depth for role searches.
+ *
+ * @param roleRecursionLimit The new recursion limit
+ */
+ public void setRoleRecursionLimit(int roleRecursionLimit) {
+
+ this.roleRecursionLimit = roleRecursionLimit;
+
+ }
+
+
+ /**
* Return the base element for role searches.
*/
public String getRoleBase() {
@@ -1405,6 +1446,69 @@
/**
+ * Add roles to a user and search for other roles containing them themselves.
+ * We search recursively with a limited depth.
+ * By default the depth is 0, and we only use direct roles.
+ * The search needs to use the distinguished role names,
+ * but to return the role names.
+ *
+ * @param depth Recursion depth, starting at zero
+ * @param context The directory context we are searching
+ * @param recursiveMap The cumulative result map of role names and DNs.
+ * @param recursiveSet The cumulative result set of role names.
+ * @param groupName The role name to add to the list.
+ * @param groupDName The distinguished name of the role.
+ *
+ * @exception NamingException if a directory server error occurs
+ */
+ private void getRolesRecursive(int depth, DirContext context, Map<String, String> recursiveMap, Set<String> recursiveSet,
+ String groupName, String groupDName) throws NamingException {
+ if (containerLog.isTraceEnabled())
+ containerLog.trace("Recursive search depth " + depth + " for group '" + groupDName + " (" + groupName + ")'");
+ // Adding the given group to the result set if not already found
+ if (!recursiveSet.contains(groupDName)) {
+ recursiveSet.add(groupDName);
+ recursiveMap.put(groupDName, groupName);
+ if (depth >= roleRecursionLimit) {
+ if (roleRecursionLimit > 0)
+ containerLog.warn("Terminating recursive role search because of recursion limit " +
+ roleRecursionLimit + ", results might be incomplete");
+ return;
+ }
+ // Prepare the parameters for searching groups
+ String filter = roleFormat.format(new String[] { groupDName });
+ SearchControls controls = new SearchControls();
+ controls.setSearchScope(roleSubtree ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE);
+ controls.setReturningAttributes(new String[] { roleName });
+ if (containerLog.isTraceEnabled()) {
+ containerLog.trace("Recursive search in role base '" + roleBase + "' for attribute '" + roleName + "'" +
+ " with filter expression '" + filter + "'");
+ }
+ // Searching groups that assign the given group
+ NamingEnumeration results = context.search(roleBase, filter, controls);
+ if (results != null) {
+ // Iterate over the resulting groups
+ try {
+ while (results.hasMore()) {
+ SearchResult result = (SearchResult) results.next();
+ Attributes attrs = result.getAttributes();
+ if (attrs == null)
+ continue;
+ String dname = getDistinguishedName(context, roleBase, result);
+ String name = getAttributeValue(roleName, attrs);
+ if (name != null && dname != null) {
+ getRolesRecursive(depth+1, context, recursiveMap, recursiveSet, name, dname);
+ }
+ }
+ } catch (PartialResultException ex) {
+ if (!adCompat)
+ throw ex;
+ }
+ }
+ }
+ }
+
+ /**
* Return a List of roles associated with the given User. Any
* roles present in the user's directory entry are supplemented by
* a directory search. If no roles are associated with this user,
@@ -1466,33 +1570,52 @@
context.search(roleBase, filter, controls);
if (results == null)
return (list); // Should never happen, but just in case ...
+
+ HashMap<String, String> groupMap = new HashMap<String, String>();
try {
while (results.hasMore()) {
SearchResult result = (SearchResult) results.next();
Attributes attrs = result.getAttributes();
if (attrs == null)
continue;
- list = addAttributeValues(roleName, attrs, list);
+ String dname = getDistinguishedName(context, roleBase, result);
+ String name = getAttributeValue(roleName, attrs);
+ if (name != null && dname != null) {
+ groupMap.put(dname, name);
+ }
}
} catch (PartialResultException ex) {
if (!adCompat)
throw ex;
}
-
+ Set<String> keys = groupMap.keySet();
if (containerLog.isTraceEnabled()) {
- if (list != null) {
- containerLog.trace(" Returning " + list.size() + " roles");
- Iterator<String> it = list.iterator();
- while (it.hasNext()) {
- containerLog.trace( " Found role " + it.next());
- }
- } else {
- containerLog.trace(" getRoles about to return null ");
+ containerLog.trace(" Found " + keys.size() + " direct roles");
+ for (Iterator<String> i = keys.iterator(); i.hasNext();) {
+ Object k = i.next();
+ containerLog.trace( " Found direct role " + k + " -> " + groupMap.get(k));
}
}
- return (list);
+ HashSet<String> recursiveSet = new HashSet<String>();
+ HashMap<String, String> recursiveMap = new HashMap<String, String>();
+
+ for (Iterator<String> i = keys.iterator(); i.hasNext();) {
+ String k = i.next();
+ getRolesRecursive(0, context, recursiveMap, recursiveSet, groupMap.get(k), k);
+ }
+
+ HashSet<String> resultSet = new HashSet<String>(list);
+ resultSet.addAll(recursiveMap.values());
+
+ if (containerLog.isTraceEnabled()) {
+ containerLog.trace(" Returning " + resultSet.size() + " roles");
+ for (Iterator<String> i = resultSet.iterator(); i.hasNext();)
+ containerLog.trace( " Found role " + i.next());
+ }
+
+ return new ArrayList<String>(resultSet);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org