You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2021/06/02 15:28:52 UTC
[tomcat] branch 10.0.x updated: Refactor principal handling for
UserDatabaseRealm
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 <re...@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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org