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/04 14:38:11 UTC
[tomcat] branch 8.5.x updated: Fix getPrincipal logic
This is an automated email from the ASF dual-hosted git repository.
remm pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/8.5.x by this push:
new a3c4a7c Fix getPrincipal logic
a3c4a7c is described below
commit a3c4a7cb22800af70a2169300687e0758405b061
Author: remm <re...@apache.org>
AuthorDate: Fri Jun 4 16:28:59 2021 +0200
Fix getPrincipal logic
Also improve tests.
---
.../apache/catalina/realm/UserDatabaseRealm.java | 27 +--
.../catalina/realm/TestGenericPrincipal.java | 7 -
.../catalina/users/MemoryUserDatabaseTests.java | 220 +++++++++++++++++++++
3 files changed, 234 insertions(+), 20 deletions(-)
diff --git a/java/org/apache/catalina/realm/UserDatabaseRealm.java b/java/org/apache/catalina/realm/UserDatabaseRealm.java
index eb63a5c..8622975 100644
--- a/java/org/apache/catalina/realm/UserDatabaseRealm.java
+++ b/java/org/apache/catalina/realm/UserDatabaseRealm.java
@@ -164,7 +164,16 @@ public class UserDatabaseRealm extends RealmBase {
*/
@Override
protected Principal getPrincipal(String username) {
- return new UserDatabasePrincipal(username);
+ UserDatabase database = getUserDatabase();
+ if (database == null) {
+ return null;
+ }
+ User user = database.findUser(username);
+ if (user == null) {
+ return null;
+ } else {
+ return new UserDatabasePrincipal(user);
+ }
}
@@ -241,21 +250,13 @@ public class UserDatabaseRealm extends RealmBase {
private static final long serialVersionUID = 1L;
private final User user;
- public UserDatabasePrincipal(String username) {
- super(username, null, null);
- UserDatabase database = getUserDatabase();
- if (database == null) {
- user = null;
- } else {
- user = database.findUser(username);
- }
+ public UserDatabasePrincipal(User user) {
+ super(user.getName(), null, null);
+ this.user = user;
}
@Override
public String[] getRoles() {
- if (user == null) {
- return super.getRoles();
- }
Set<String> roles = new HashSet<>();
Iterator<Role> uroles = user.getRoles();
while (uroles.hasNext()) {
@@ -282,7 +283,7 @@ public class UserDatabaseRealm extends RealmBase {
return false;
}
UserDatabase database = getUserDatabase();
- if (user == null || database == null) {
+ if (database == null) {
return super.hasRole(role);
}
Role dbrole = database.findRole(role);
diff --git a/test/org/apache/catalina/realm/TestGenericPrincipal.java b/test/org/apache/catalina/realm/TestGenericPrincipal.java
index 9cd2e04..c1507de 100644
--- a/test/org/apache/catalina/realm/TestGenericPrincipal.java
+++ b/test/org/apache/catalina/realm/TestGenericPrincipal.java
@@ -57,13 +57,6 @@ 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/test/org/apache/catalina/users/MemoryUserDatabaseTests.java b/test/org/apache/catalina/users/MemoryUserDatabaseTests.java
new file mode 100644
index 0000000..f8e168f
--- /dev/null
+++ b/test/org/apache/catalina/users/MemoryUserDatabaseTests.java
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.users;
+
+import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.security.Principal;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.catalina.User;
+import org.apache.catalina.realm.GenericPrincipal;
+import org.apache.catalina.realm.UserDatabaseRealm;
+
+public class MemoryUserDatabaseTests {
+ private static File TEST_FILE = new File(System.getProperty("java.io.tmpdir"), "tomcat-users.xml");
+
+ private static MemoryUserDatabase db;
+
+ @BeforeClass
+ public static void createSampleDB()
+ throws Exception {
+
+ try(BufferedWriter out = new BufferedWriter(new FileWriter(TEST_FILE))) {
+ out.write("<?xml version=\"1.0\" ?>"
+ + "<tomcat-users xmlns=\"http://tomcat.apache.org/xml\""
+ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
+ + " xsi:schemaLocation=\"http://tomcat.apache.org/xml/tomcat-users.xsd\""
+ + " version=\"1.0\">"
+ + "<role rolename=\"testrole\" />"
+ + "<group groupname=\"testgroup\" />"
+ + "<user username=\"admin\" password=\"sekr3t\" roles=\"testrole, otherrole\" groups=\"testgroup, othergroup\" />"
+ + "</tomcat-users>");
+ }
+
+ db = new MemoryUserDatabase();
+ db.setPathname(TEST_FILE.toURI().toURL().toString());
+ db.open();
+ }
+
+ @AfterClass
+ public static void cleanup() {
+ Assert.assertTrue(TEST_FILE.delete());
+ }
+
+ @Test
+ public void testLoadUserDatabase()
+ throws Exception {
+ assertPrincipalNames(new String[] { "testrole", "otherrole"}, db.getRoles());
+ assertPrincipalNames(new String[] { "testgroup", "othergroup"}, db.getGroups());
+
+ Iterator<User> users = db.getUsers();
+
+ Assert.assertTrue("No users found", users.hasNext());
+
+ User user = users.next();
+
+ Assert.assertEquals("admin", user.getName());
+ Assert.assertNull(user.getFullName());
+ Assert.assertEquals("sekr3t", user.getPassword());
+
+ assertPrincipalNames(new String[] { "testrole", "otherrole"}, user.getRoles());
+ assertPrincipalNames(new String[] { "testgroup", "othergroup"}, user.getGroups());
+ }
+
+ public void testReloadUserDatabase()
+ throws Exception {
+ // Change the database on the disk and reload
+
+ try(BufferedWriter out = new BufferedWriter(new FileWriter(TEST_FILE))) {
+ out.write("<?xml version=\"1.0\" ?>"
+ + "<tomcat-users xmlns=\"http://tomcat.apache.org/xml\""
+ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
+ + " xsi:schemaLocation=\"http://tomcat.apache.org/xml/tomcat-users.xsd\""
+ + " version=\"1.0\">"
+ + "<role rolename=\"foo\" />"
+ + "<group groupname=\"bar\" />"
+ + "<user username=\"root\" password=\"sup3Rsekr3t\" roles=\"foo, bar\" groups=\"bar, foo\" />"
+ + "</tomcat-users>");
+
+ db.open();
+ }
+
+ assertPrincipalNames(new String[] { "foo", "bar"}, db.getRoles());
+ assertPrincipalNames(new String[] { "bar", "foo"}, db.getGroups());
+
+ Iterator<User> users = db.getUsers();
+
+ Assert.assertTrue("No users found", users.hasNext());
+
+ User user = users.next();
+
+ Assert.assertEquals("root", user.getName());
+ Assert.assertNull(user.getFullName());
+ Assert.assertEquals("sup3Rsekr3t", user.getPassword());
+
+ assertPrincipalNames(new String[] { "foo", "bar"}, user.getRoles());
+ assertPrincipalNames(new String[] { "bar", "foo"}, user.getGroups());
+ }
+
+ @Test
+ public void testMultithreadedMutateUserDatabase()
+ throws Exception {
+ // Generate lots of concurrent load on the user database
+ Runnable job = new Runnable() {
+ @Override
+ public void run() {
+ for(int i=0; i<10; ++i) {
+ db.createUser("newUser-" + Thread.currentThread().getName() + "-" + i, "x", null);
+ }
+ }
+ };
+
+ int numThreads = 100;
+ Thread[] threads = new Thread[numThreads + 1];
+ for(int i=0; i<numThreads; ++i) {
+ threads[i] = new Thread(job);
+ }
+
+ // Let's
+ threads[numThreads] = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try { db.open(); }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ ++numThreads;
+
+ for(int i=0; i<numThreads; ++i) {
+ threads[i].start();
+ }
+
+ for(int i=0; i<numThreads; ++i) {
+ threads[i].join();
+ }
+
+ // Remove all those extra users
+ Iterator<User> users = db.getUsers();
+ for(; users.hasNext();) {
+ User user = users.next();
+ if(user.getUsername().startsWith("newUser")) {
+ db.removeUser(user);
+ }
+ }
+
+ users = db.getUsers();
+
+ Assert.assertTrue("No users found", users.hasNext());
+
+ User user = users.next();
+
+ Assert.assertEquals("admin", user.getName());
+ Assert.assertNull(user.getFullName());
+ Assert.assertEquals("sekr3t", user.getPassword());
+
+ assertPrincipalNames(new String[] { "testrole", "otherrole"}, user.getRoles());
+ assertPrincipalNames(new String[] { "testgroup", "othergroup"}, user.getGroups());
+ }
+
+ @Test
+ public void testSerializePrincipal()
+ throws Exception {
+ UserDatabaseRealm realm = new UserDatabaseRealm();
+ User user = db.findUser("admin");
+ GenericPrincipal gpIn = realm.new UserDatabasePrincipal(user);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bos);
+ oos.writeObject(gpIn);
+
+ byte[] data = bos.toByteArray();
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(data);
+ ObjectInputStream ois = new ObjectInputStream(bis);
+ GenericPrincipal gpOut = (GenericPrincipal) ois.readObject();
+
+ Assert.assertEquals("admin", gpOut.getName());
+ assertPrincipalNames(gpOut.getRoles(), user.getRoles());
+ }
+
+ private void assertPrincipalNames(String[] expectedNames, Iterator<? extends Principal> i) {
+ HashSet<String> names = new HashSet<>(Arrays.asList(expectedNames));
+
+ int j=0;
+ while(i.hasNext()) {
+ Assert.assertTrue(names.contains(i.next().getName()));
+ j++;
+ }
+
+ Assert.assertEquals(expectedNames.length, j);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org