This is an automated email from the ASF dual-hosted git repository. remm pushed a commit to branch 10.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/10.0.x by this push: new 164df51 Refactor principal handling for UserDatabaseRealm 164df51 is described below commit 164df51c78ed8b15f757db99b9ab84e50219156d Author: remm <r...@apache.org> AuthorDate: Wed Jun 2 17:28:23 2021 +0200 Refactor principal handling for UserDatabaseRealm Now extends GenericPrincipal for easier integration in the rest of Tomcat. --- .../apache/catalina/realm/UserDatabaseRealm.java | 165 ++++++++------------- .../catalina/realm/TestGenericPrincipal.java | 7 + webapps/docs/changelog.xml | 4 + 3 files changed, 76 insertions(+), 100 deletions(-) diff --git a/java/org/apache/catalina/realm/UserDatabaseRealm.java b/java/org/apache/catalina/realm/UserDatabaseRealm.java index f30c24a..714fd50 100644 --- a/java/org/apache/catalina/realm/UserDatabaseRealm.java +++ b/java/org/apache/catalina/realm/UserDatabaseRealm.java @@ -17,9 +17,10 @@ package org.apache.catalina.realm; import java.security.Principal; -import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.Iterator; -import java.util.List; +import java.util.Set; import javax.naming.Context; @@ -28,7 +29,6 @@ import org.apache.catalina.LifecycleException; import org.apache.catalina.Role; import org.apache.catalina.User; import org.apache.catalina.UserDatabase; -import org.apache.catalina.Wrapper; import org.apache.naming.ContextBindings; import org.apache.tomcat.util.ExceptionUtils; @@ -112,69 +112,6 @@ public class UserDatabaseRealm extends RealmBase { } - // --------------------------------------------------------- Public Methods - - /** - * Return <code>true</code> if the specified Principal has the specified - * security role, within the context of this Realm; otherwise return - * <code>false</code>. This implementation returns <code>true</code> if the - * <code>User</code> has the role, or if any <code>Group</code> that the - * <code>User</code> is a member of has the role. - * - * @param principal Principal for whom the role is to be checked - * @param role Security role to be checked - */ - @Override - public boolean hasRole(Wrapper wrapper, Principal principal, String role) { - - UserDatabase database = getUserDatabase(); - if (database == null) { - return false; - } - - // Check for a role alias defined in a <security-role-ref> element - if (wrapper != null) { - String realRole = wrapper.findSecurityReference(role); - if (realRole != null) { - role = realRole; - } - } - if (principal instanceof GenericPrincipal) { - GenericPrincipal gp = (GenericPrincipal) principal; - if (gp.getUserPrincipal() instanceof UserDatabasePrincipal) { - principal = database.findUser(gp.getName()); - } - } - if (!(principal instanceof User)) { - // Play nice with SSO and mixed Realms - // No need to pass the wrapper here because role mapping has been - // performed already a few lines above - return super.hasRole(null, principal, role); - } - if ("*".equals(role)) { - return true; - } else if (role == null) { - return false; - } - User user = (User) principal; - Role dbrole = database.findRole(role); - if (dbrole == null) { - return false; - } - if (user.isInRole(dbrole)) { - return true; - } - Iterator<Group> groups = user.getGroups(); - while (groups.hasNext()) { - Group group = groups.next(); - if (group.isInRole(dbrole)) { - return true; - } - } - return false; - } - - // ------------------------------------------------------ Protected Methods @Override @@ -211,33 +148,7 @@ public class UserDatabaseRealm extends RealmBase { */ @Override protected Principal getPrincipal(String username) { - UserDatabase database = getUserDatabase(); - if (database == null) { - return null; - } - - User user = database.findUser(username); - if (user == null) { - return null; - } - - List<String> roles = new ArrayList<>(); - Iterator<Role> uroles = user.getRoles(); - while (uroles.hasNext()) { - Role role = uroles.next(); - roles.add(role.getName()); - } - Iterator<Group> groups = user.getGroups(); - while (groups.hasNext()) { - Group group = groups.next(); - uroles = group.getRoles(); - while (uroles.hasNext()) { - Role role = uroles.next(); - roles.add(role.getName()); - } - } - return new GenericPrincipal(username, roles, - new UserDatabasePrincipal(username)); + return new UserDatabasePrincipal(username); } @@ -261,7 +172,9 @@ public class UserDatabaseRealm extends RealmBase { database = (UserDatabase) context.lookup(resourceName); } catch (Throwable e) { ExceptionUtils.handleThrowable(e); - containerLog.error(sm.getString("userDatabaseRealm.lookup", resourceName), e); + if (containerLog != null) { + containerLog.error(sm.getString("userDatabaseRealm.lookup", resourceName), e); + } database = null; } } @@ -308,14 +221,66 @@ public class UserDatabaseRealm extends RealmBase { } - private static class UserDatabasePrincipal implements Principal { - private final String name; - private UserDatabasePrincipal(String name) { - this.name = name; + public final class UserDatabasePrincipal extends GenericPrincipal { + private static final long serialVersionUID = 1L; + private final User user; + + public UserDatabasePrincipal(String username) { + super(username); + UserDatabase database = getUserDatabase(); + if (database == null) { + user = null; + } else { + user = database.findUser(username); + } + } + + @Override + public String[] getRoles() { + if (user == null) { + return super.getRoles(); + } + Set<String> roles = new HashSet<>(); + Iterator<Role> uroles = user.getRoles(); + while (uroles.hasNext()) { + Role role = uroles.next(); + roles.add(role.getName()); + } + Iterator<Group> groups = user.getGroups(); + while (groups.hasNext()) { + Group group = groups.next(); + uroles = group.getRoles(); + while (uroles.hasNext()) { + Role role = uroles.next(); + roles.add(role.getName()); + } + } + return roles.toArray(new String[0]); } + @Override - public String getName() { - return name; + public boolean hasRole(String role) { + if ("*".equals(role)) { + return true; + } else if (role == null) { + return false; + } + UserDatabase database = getUserDatabase(); + if (user == null || database == null) { + return super.hasRole(role); + } + Role dbrole = database.findRole(role); + if (dbrole == null) { + return false; + } + return user.isInRole(dbrole); } + + private Object writeReplace() { + // Replace with a static principal disconnected from the database + return new GenericPrincipal(getName(), Arrays.asList(getRoles())); + } + } + } diff --git a/test/org/apache/catalina/realm/TestGenericPrincipal.java b/test/org/apache/catalina/realm/TestGenericPrincipal.java index 5a99415..b2ac92f 100644 --- a/test/org/apache/catalina/realm/TestGenericPrincipal.java +++ b/test/org/apache/catalina/realm/TestGenericPrincipal.java @@ -56,6 +56,13 @@ public class TestGenericPrincipal { doTest(gpIn); } + @Test + public void testSerialize04() throws ClassNotFoundException, IOException { + UserDatabaseRealm realm = new UserDatabaseRealm(); + GenericPrincipal gpIn = realm.new UserDatabasePrincipal(USER); + doTest(gpIn); + } + private void doTest(GenericPrincipal gpIn) throws ClassNotFoundException, IOException { GenericPrincipal gpOut = serializeAndDeserialize(gpIn); diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 5e74509..41b1899 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -139,6 +139,10 @@ AprLifecycleListener does not show dev version suffix for libtcnative and libapr. (michaelo) </fix> + <update> + Refactor principal handling in <code>UserDatabaseRealm</code> using + an inner class that extends <code>GenericPrincipal</code>. (remm) + </update> </changelog> </subsection> <subsection name="Coyote"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org