diff --git a/demos/demo-jaas-webapp/src/main/config/modules/demo-jaas.mod b/demos/demo-jaas-webapp/src/main/config/modules/demo-jaas.mod
index a27bf23cd1a..8c97d60007c 100644
--- a/demos/demo-jaas-webapp/src/main/config/modules/demo-jaas.mod
+++ b/demos/demo-jaas-webapp/src/main/config/modules/demo-jaas.mod
@@ -14,7 +14,6 @@ jdbc
jsp
annotations
ext
-demo-realm
[files]
basehome:modules/demo.d/demo-jaas.xml|webapps/demo-jaas.xml
@@ -22,6 +21,6 @@ basehome:modules/demo.d/demo-login.conf|etc/demo-login.conf
basehome:modules/demo.d/demo-login.properties|etc/demo-login.properties
maven://org.eclipse.jetty.demos/demo-jaas-webapp/${jetty.version}/war|webapps/demo-jaas.war
-[ini-template]
+[ini]
# Enable security via jaas, and configure it
-jetty.jaas.login.conf=etc/demo-login.conf
\ No newline at end of file
+jetty.jaas.login.conf?=etc/demo-login.conf
diff --git a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/JAASLoginService.java b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/JAASLoginService.java
index f29ab99de88..a6d17256e9d 100644
--- a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/JAASLoginService.java
+++ b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/JAASLoginService.java
@@ -231,12 +231,14 @@ public class JAASLoginService extends ContainerLifeCycle implements LoginService
}
catch (Exception e)
{
- LOG.trace("IGNORED", e);
+ if (LOG.isDebugEnabled())
+ LOG.debug("Login error", e);
}
finally
{
INSTANCE.remove();
}
+
return null;
}
diff --git a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/JAASUserPrincipal.java b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/JAASUserPrincipal.java
index 9eb707f2d39..33a1f4a8033 100644
--- a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/JAASUserPrincipal.java
+++ b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/JAASUserPrincipal.java
@@ -26,7 +26,7 @@ import javax.security.auth.login.LoginContext;
* JAASUserPrincipal
*
* Implements the JAAS version of the
- * org.eclipse.jetty.http.UserPrincipal interface.
+ * org.eclipse.jetty.security.UserPrincipal interface.
*/
public class JAASUserPrincipal implements Principal
{
diff --git a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/AbstractDatabaseLoginModule.java b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/AbstractDatabaseLoginModule.java
index acd04e7a90b..b23249cba1b 100644
--- a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/AbstractDatabaseLoginModule.java
+++ b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/AbstractDatabaseLoginModule.java
@@ -27,6 +27,7 @@ import java.util.Map;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
+import org.eclipse.jetty.security.UserPrincipal;
import org.eclipse.jetty.util.security.Credential;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -57,11 +58,11 @@ public abstract class AbstractDatabaseLoginModule extends AbstractLoginModule
*/
public abstract Connection getConnection() throws Exception;
- public class JDBCUserInfo extends UserInfo
+ public class JDBCUser extends JAASUser
{
- public JDBCUserInfo(String userName, Credential credential)
+ public JDBCUser(UserPrincipal user)
{
- super(userName, credential);
+ super(user);
}
@Override
@@ -79,7 +80,7 @@ public abstract class AbstractDatabaseLoginModule extends AbstractLoginModule
* @throws Exception if unable to get the user info
*/
@Override
- public UserInfo getUserInfo(String userName)
+ public JAASUser getUser(String userName)
throws Exception
{
try (Connection connection = getConnection())
@@ -100,11 +101,9 @@ public abstract class AbstractDatabaseLoginModule extends AbstractLoginModule
}
if (dbCredential == null)
- {
return null;
- }
- return new JDBCUserInfo(userName, Credential.getCredential(dbCredential));
+ return new JDBCUser(new UserPrincipal(userName, Credential.getCredential(dbCredential)));
}
}
diff --git a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/AbstractLoginModule.java b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/AbstractLoginModule.java
index 2bbb253b7f3..eb3f18f3d37 100644
--- a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/AbstractLoginModule.java
+++ b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/AbstractLoginModule.java
@@ -19,11 +19,11 @@
package org.eclipse.jetty.jaas.spi;
import java.io.IOException;
-import java.security.Principal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
@@ -34,9 +34,10 @@ import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
-import org.eclipse.jetty.jaas.JAASPrincipal;
import org.eclipse.jetty.jaas.JAASRole;
import org.eclipse.jetty.jaas.callback.ObjectCallback;
+import org.eclipse.jetty.security.UserPrincipal;
+import org.eclipse.jetty.util.thread.AutoLock;
/**
* AbstractLoginModule
@@ -50,35 +51,22 @@ public abstract class AbstractLoginModule implements LoginModule
private boolean authState = false;
private boolean commitState = false;
- private JAASUserInfo currentUser;
+ private JAASUser currentUser;
private Subject subject;
- /**
- * JAASUserInfo
- *
- * This class unites the UserInfo data with jaas concepts
- * such as Subject and Principals
- */
- public class JAASUserInfo
+ public abstract static class JAASUser
{
- private UserInfo user;
- private Principal principal;
- private List roles;
-
- public JAASUserInfo(UserInfo u)
+ private final UserPrincipal _user;
+ private List _roles;
+
+ public JAASUser(UserPrincipal u)
{
- this.user = u;
- this.principal = new JAASPrincipal(u.getUserName());
+ _user = u;
}
public String getUserName()
{
- return this.user.getUserName();
- }
-
- public Principal getPrincipal()
- {
- return this.principal;
+ return _user.getName();
}
/**
@@ -86,12 +74,12 @@ public abstract class AbstractLoginModule implements LoginModule
*/
public void setJAASInfo(Subject subject)
{
- subject.getPrincipals().add(this.principal);
- if (this.user.getCredential() != null)
- {
- subject.getPrivateCredentials().add(this.user.getCredential());
- }
- subject.getPrincipals().addAll(roles);
+ if (_user == null)
+ return;
+
+ _user.configureSubject(subject);
+ if (_roles != null)
+ subject.getPrincipals().addAll(_roles);
}
/**
@@ -99,35 +87,29 @@ public abstract class AbstractLoginModule implements LoginModule
*/
public void unsetJAASInfo(Subject subject)
{
- subject.getPrincipals().remove(this.principal);
- if (this.user.getCredential() != null)
- {
- subject.getPrivateCredentials().remove(this.user.getCredential());
- }
- subject.getPrincipals().removeAll(this.roles);
+ if (_user == null)
+ return;
+ _user.deconfigureSubject(subject);
+ if (_roles != null)
+ subject.getPrincipals().removeAll(_roles);
}
public boolean checkCredential(Object suppliedCredential)
{
- return this.user.checkCredential(suppliedCredential);
+ return _user.authenticate(suppliedCredential);
}
public void fetchRoles() throws Exception
{
- this.user.fetchRoles();
- this.roles = new ArrayList();
- if (this.user.getRoleNames() != null)
- {
- Iterator itor = this.user.getRoleNames().iterator();
- while (itor.hasNext())
- {
- this.roles.add(new JAASRole((String)itor.next()));
- }
- }
+ List rolenames = doFetchRoles();
+ if (rolenames != null)
+ _roles = rolenames.stream().map(JAASRole::new).collect(Collectors.toList());
}
+
+ public abstract List doFetchRoles() throws Exception;
}
- public abstract UserInfo getUserInfo(String username) throws Exception;
+ public abstract JAASUser getUser(String username) throws Exception;
public Subject getSubject()
{
@@ -139,12 +121,12 @@ public abstract class AbstractLoginModule implements LoginModule
this.subject = s;
}
- public JAASUserInfo getCurrentUser()
+ public JAASUser getCurrentUser()
{
return this.currentUser;
}
- public void setCurrentUser(JAASUserInfo u)
+ public void setCurrentUser(JAASUser u)
{
this.currentUser = u;
}
@@ -252,15 +234,15 @@ public abstract class AbstractLoginModule implements LoginModule
throw new FailedLoginException();
}
- UserInfo userInfo = getUserInfo(webUserName);
+ JAASUser user = getUser(webUserName);
- if (userInfo == null)
+ if (user == null)
{
setAuthenticated(false);
throw new FailedLoginException();
}
- currentUser = new JAASUserInfo(userInfo);
+ currentUser = user;
setAuthenticated(currentUser.checkCredential(webCredential));
if (isAuthenticated())
diff --git a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/LdapLoginModule.java b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/LdapLoginModule.java
index 8b4798f38a0..ed60381c8a0 100644
--- a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/LdapLoginModule.java
+++ b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/LdapLoginModule.java
@@ -45,6 +45,7 @@ import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.LoginException;
import org.eclipse.jetty.jaas.callback.ObjectCallback;
+import org.eclipse.jetty.security.UserPrincipal;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.security.Credential;
import org.slf4j.Logger;
@@ -179,18 +180,13 @@ public class LdapLoginModule extends AbstractLoginModule
private DirContext _rootContext;
- public class LDAPUserInfo extends UserInfo
+ public class LDAPUser extends JAASUser
{
Attributes attributes;
- /**
- * @param userName the user name
- * @param credential the credential
- * @param attributes the user {@link Attributes}
- */
- public LDAPUserInfo(String userName, Credential credential, Attributes attributes)
+ public LDAPUser(UserPrincipal user, Attributes attributes)
{
- super(userName, credential);
+ super(user);
this.attributes = attributes;
}
@@ -201,6 +197,25 @@ public class LdapLoginModule extends AbstractLoginModule
}
}
+ public class LDAPBindingUser extends JAASUser
+ {
+ DirContext _context;
+ String _userDn;
+
+ public LDAPBindingUser(UserPrincipal user, DirContext context, String userDn)
+ {
+ super(user);
+ _context = context;
+ _userDn = userDn;
+ }
+
+ @Override
+ public List doFetchRoles() throws Exception
+ {
+ return getUserRolesByDn(_context, _userDn);
+ }
+ }
+
/**
* get the available information about the user
*
@@ -214,19 +229,17 @@ public class LdapLoginModule extends AbstractLoginModule
* @throws Exception if unable to get the user info
*/
@Override
- public UserInfo getUserInfo(String username) throws Exception
+ public JAASUser getUser(String username) throws Exception
{
Attributes attributes = getUserAttributes(username);
String pwdCredential = getUserCredentials(attributes);
if (pwdCredential == null)
- {
return null;
- }
pwdCredential = convertCredentialLdapToJetty(pwdCredential);
Credential credential = Credential.getCredential(pwdCredential);
- return new LDAPUserInfo(username, credential, attributes);
+ return new LDAPUser(new UserPrincipal(username, credential), attributes);
}
protected String doRFC2254Encoding(String inputString)
@@ -421,7 +434,7 @@ public class LdapLoginModule extends AbstractLoginModule
else
{
// This sets read and the credential
- UserInfo userInfo = getUserInfo(webUserName);
+ JAASUser userInfo = getUser(webUserName);
if (userInfo == null)
{
@@ -429,7 +442,7 @@ public class LdapLoginModule extends AbstractLoginModule
return false;
}
- setCurrentUser(new JAASUserInfo(userInfo));
+ setCurrentUser(userInfo);
if (webCredential instanceof String)
authed = credentialLogin(Credential.getCredential((String)webCredential));
@@ -520,12 +533,8 @@ public class LdapLoginModule extends AbstractLoginModule
try
{
DirContext dirContext = new InitialDirContext(environment);
- List roles = getUserRolesByDn(dirContext, userDn);
-
- UserInfo userInfo = new UserInfo(username, null, roles);
- setCurrentUser(new JAASUserInfo(userInfo));
+ setCurrentUser(new LDAPBindingUser(new UserPrincipal(username, null), dirContext, userDn));
setAuthenticated(true);
-
return true;
}
catch (javax.naming.AuthenticationException e)
diff --git a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/PropertyFileLoginModule.java b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/PropertyFileLoginModule.java
index 63ca7289b2a..0025cce5e35 100644
--- a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/PropertyFileLoginModule.java
+++ b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/PropertyFileLoginModule.java
@@ -18,6 +18,7 @@
package org.eclipse.jetty.jaas.spi;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -27,8 +28,9 @@ import javax.security.auth.callback.CallbackHandler;
import org.eclipse.jetty.jaas.JAASLoginService;
import org.eclipse.jetty.jaas.PropertyUserStoreManager;
-import org.eclipse.jetty.security.AbstractLoginService;
import org.eclipse.jetty.security.PropertyUserStore;
+import org.eclipse.jetty.security.RolePrincipal;
+import org.eclipse.jetty.security.UserPrincipal;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.security.Credential;
import org.slf4j.Logger;
@@ -122,22 +124,23 @@ public class PropertyFileLoginModule extends AbstractLoginModule
* @throws Exception if unable to get the user information
*/
@Override
- public UserInfo getUserInfo(String userName) throws Exception
+ public JAASUser getUser(String userName) throws Exception
{
- LOG.debug("Checking PropertyUserStore {} for {}", _store.getConfig(), userName);
- UserIdentity userIdentity = _store.getUserIdentity(userName);
- if (userIdentity == null)
+ if (LOG.isDebugEnabled())
+ LOG.debug("Checking PropertyUserStore {} for {}", _store.getConfig(), userName);
+ UserPrincipal up = _store.getUserPrincipal(userName);
+ if (up == null)
return null;
- //TODO in future versions change the impl of PropertyUserStore so its not
- //storing Subjects etc, just UserInfo
- Set principals = userIdentity.getSubject().getPrincipals(AbstractLoginService.RolePrincipal.class);
-
- List roles = principals.stream()
- .map(AbstractLoginService.RolePrincipal::getName)
- .collect(Collectors.toList());
-
- Credential credential = (Credential)userIdentity.getSubject().getPrivateCredentials().iterator().next();
- return new UserInfo(userName, credential, roles);
+ List rps = _store.getRolePrincipals(userName);
+ List roles = rps == null ? Collections.emptyList() : rps.stream().map(RolePrincipal::getName).collect(Collectors.toList());
+ return new JAASUser(up)
+ {
+ @Override
+ public List doFetchRoles()
+ {
+ return roles;
+ }
+ };
}
}
diff --git a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/UserInfo.java b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/UserInfo.java
deleted file mode 100644
index 6b2a9a64e43..00000000000
--- a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/UserInfo.java
+++ /dev/null
@@ -1,113 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under
-// the terms of the Eclipse Public License 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0
-//
-// This Source Code may also be made available under the following
-// Secondary Licenses when the conditions for such availability set
-// forth in the Eclipse Public License, v. 2.0 are satisfied:
-// the Apache License v2.0 which is available at
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-package org.eclipse.jetty.jaas.spi;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.eclipse.jetty.util.security.Credential;
-import org.eclipse.jetty.util.thread.AutoLock;
-
-/**
- * UserInfo
- *
- * This is the information read from the external source
- * about a user.
- *
- * Can be cached.
- */
-public class UserInfo
-{
- private final AutoLock _lock = new AutoLock();
- private String _userName;
- private Credential _credential;
- protected List _roleNames = new ArrayList<>();
- protected boolean _rolesLoaded = false;
-
- /**
- * @param userName the user name
- * @param credential the credential
- * @param roleNames a {@link List} of role name
- */
- public UserInfo(String userName, Credential credential, List roleNames)
- {
- _userName = userName;
- _credential = credential;
- if (roleNames != null)
- {
- _roleNames.addAll(roleNames);
- _rolesLoaded = true;
- }
- }
-
- /**
- * @param userName the user name
- * @param credential the credential
- */
- public UserInfo(String userName, Credential credential)
- {
- this(userName, credential, null);
- }
-
- /**
- * Should be overridden by subclasses to obtain
- * role info
- *
- * @return List of role associated to the user
- * @throws Exception if the roles cannot be retrieved
- */
- public List doFetchRoles()
- throws Exception
- {
- return Collections.emptyList();
- }
-
- public void fetchRoles() throws Exception
- {
- try (AutoLock l = _lock.lock())
- {
- if (!_rolesLoaded)
- {
- _roleNames.addAll(doFetchRoles());
- _rolesLoaded = true;
- }
- }
- }
-
- public String getUserName()
- {
- return this._userName;
- }
-
- public List getRoleNames()
- {
- return Collections.unmodifiableList(_roleNames);
- }
-
- public boolean checkCredential(Object suppliedCredential)
- {
- return _credential.check(suppliedCredential);
- }
-
- protected Credential getCredential()
- {
- return _credential;
- }
-}
diff --git a/jetty-jaas/src/test/java/org/eclipse/jetty/jaas/TestLoginModule.java b/jetty-jaas/src/test/java/org/eclipse/jetty/jaas/TestLoginModule.java
index 20868dbe870..187c1d3049f 100644
--- a/jetty-jaas/src/test/java/org/eclipse/jetty/jaas/TestLoginModule.java
+++ b/jetty-jaas/src/test/java/org/eclipse/jetty/jaas/TestLoginModule.java
@@ -18,12 +18,14 @@
package org.eclipse.jetty.jaas;
+import java.util.Collections;
+import java.util.List;
import javax.security.auth.callback.Callback;
import javax.security.auth.login.LoginException;
import org.eclipse.jetty.jaas.callback.ServletRequestCallback;
import org.eclipse.jetty.jaas.spi.AbstractLoginModule;
-import org.eclipse.jetty.jaas.spi.UserInfo;
+import org.eclipse.jetty.security.UserPrincipal;
import org.eclipse.jetty.util.ArrayUtil;
import org.eclipse.jetty.util.security.Password;
@@ -34,9 +36,16 @@ public class TestLoginModule extends AbstractLoginModule
public ServletRequestCallback _callback = new ServletRequestCallback();
@Override
- public UserInfo getUserInfo(String username) throws Exception
- {
- return new UserInfo(username, new Password("aaa"));
+ public JAASUser getUser(String username) throws Exception
+ {
+ return new JAASUser(new UserPrincipal(username, new Password("aaa")))
+ {
+ @Override
+ public List doFetchRoles() throws Exception
+ {
+ return Collections.emptyList();
+ }
+ };
}
@Override
diff --git a/jetty-jaspi/src/test/java/org/eclipse/jetty/security/jaspi/JaspiTest.java b/jetty-jaspi/src/test/java/org/eclipse/jetty/security/jaspi/JaspiTest.java
index 6dbc96c7840..e2a7b6fcfa5 100644
--- a/jetty-jaspi/src/test/java/org/eclipse/jetty/security/jaspi/JaspiTest.java
+++ b/jetty-jaspi/src/test/java/org/eclipse/jetty/security/jaspi/JaspiTest.java
@@ -19,9 +19,12 @@
package org.eclipse.jetty.security.jaspi;
import java.io.IOException;
+import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
@@ -29,6 +32,8 @@ import jakarta.servlet.http.HttpServletResponse;
import org.eclipse.jetty.security.AbstractLoginService;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
+import org.eclipse.jetty.security.RolePrincipal;
+import org.eclipse.jetty.security.UserPrincipal;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
@@ -55,7 +60,7 @@ public class JaspiTest
public class TestLoginService extends AbstractLoginService
{
protected Map _users = new HashMap<>();
- protected Map _roles = new HashMap();
+ protected Map> _roles = new HashMap<>();
public TestLoginService(String name)
{
@@ -66,11 +71,15 @@ public class JaspiTest
{
UserPrincipal userPrincipal = new UserPrincipal(username, credential);
_users.put(username, userPrincipal);
- _roles.put(username, roles);
+ if (roles != null)
+ {
+ List rps = Arrays.stream(roles).map(RolePrincipal::new).collect(Collectors.toList());
+ _roles.put(username, rps);
+ }
}
@Override
- protected String[] loadRoleInfo(UserPrincipal user)
+ protected List loadRoleInfo(UserPrincipal user)
{
return _roles.get(user.getName());
}
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java
index 5bf7a507484..9670f2322ad 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java
@@ -27,6 +27,7 @@ import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
+import java.util.stream.Collectors;
import javax.naming.InitialContext;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
@@ -35,16 +36,17 @@ import javax.sql.DataSource;
import org.eclipse.jetty.plus.jndi.NamingEntryUtil;
import org.eclipse.jetty.security.AbstractLoginService;
import org.eclipse.jetty.security.IdentityService;
+import org.eclipse.jetty.security.RolePrincipal;
+import org.eclipse.jetty.security.UserPrincipal;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.security.Credential;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * DataSourceUserRealm
+ * DataSourceLoginService
*
- * Obtain user/password/role information from a database
- * via jndi DataSource.
+ * Obtain user/password/role information from a database via jndi DataSource.
*/
public class DataSourceLoginService extends AbstractLoginService
{
@@ -264,7 +266,7 @@ public class DataSourceLoginService extends AbstractLoginService
}
@Override
- public String[] loadRoleInfo(UserPrincipal user)
+ public List loadRoleInfo(UserPrincipal user)
{
DBUserPrincipal dbuser = (DBUserPrincipal)user;
@@ -280,11 +282,9 @@ public class DataSourceLoginService extends AbstractLoginService
try (ResultSet rs2 = statement2.executeQuery())
{
while (rs2.next())
- {
roles.add(rs2.getString(_roleTableRoleField));
- }
- return roles.toArray(new String[roles.size()]);
+ return roles.stream().map(RolePrincipal::new).collect(Collectors.toList());
}
}
}
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/AbstractLoginService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/AbstractLoginService.java
index 1f1152d35a6..6649cffbd2a 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/AbstractLoginService.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/AbstractLoginService.java
@@ -18,19 +18,21 @@
package org.eclipse.jetty.security;
-import java.io.Serializable;
-import java.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
import javax.security.auth.Subject;
import jakarta.servlet.ServletRequest;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
-import org.eclipse.jetty.util.security.Credential;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* AbstractLoginService
+ *
+ * Base class for LoginServices that allows subclasses to provide the user authentication and authorization information,
+ * but provides common behaviour such as handling authentication.
*/
public abstract class AbstractLoginService extends ContainerLifeCycle implements LoginService
{
@@ -40,65 +42,7 @@ public abstract class AbstractLoginService extends ContainerLifeCycle implements
protected String _name;
protected boolean _fullValidate = false;
- /**
- * RolePrincipal
- */
- public static class RolePrincipal implements Principal, Serializable
- {
- private static final long serialVersionUID = 2998397924051854402L;
- private final String _roleName;
-
- public RolePrincipal(String name)
- {
- _roleName = name;
- }
-
- @Override
- public String getName()
- {
- return _roleName;
- }
- }
-
- /**
- * UserPrincipal
- */
- public static class UserPrincipal implements Principal, Serializable
- {
- private static final long serialVersionUID = -6226920753748399662L;
- private final String _name;
- private final Credential _credential;
-
- public UserPrincipal(String name, Credential credential)
- {
- _name = name;
- _credential = credential;
- }
-
- public boolean authenticate(Object credentials)
- {
- return _credential != null && _credential.check(credentials);
- }
-
- public boolean authenticate(Credential c)
- {
- return (_credential != null && c != null && _credential.equals(c));
- }
-
- @Override
- public String getName()
- {
- return _name;
- }
-
- @Override
- public String toString()
- {
- return _name;
- }
- }
-
- protected abstract String[] loadRoleInfo(UserPrincipal user);
+ protected abstract List loadRoleInfo(UserPrincipal user);
protected abstract UserPrincipal loadUserInfo(String username);
@@ -155,18 +99,22 @@ public abstract class AbstractLoginService extends ContainerLifeCycle implements
if (userPrincipal != null && userPrincipal.authenticate(credentials))
{
//safe to load the roles
- String[] roles = loadRoleInfo(userPrincipal);
+ List roles = loadRoleInfo(userPrincipal);
+ List roleNames = new ArrayList<>();
Subject subject = new Subject();
- subject.getPrincipals().add(userPrincipal);
- subject.getPrivateCredentials().add(userPrincipal._credential);
+ userPrincipal.configureSubject(subject);
if (roles != null)
- for (String role : roles)
+ {
+ roles.forEach(p ->
{
- subject.getPrincipals().add(new RolePrincipal(role));
- }
+ p.configureForSubject(subject);
+ roleNames.add(p.getName());
+ });
+ }
+
subject.setReadOnly();
- return _identityService.newUserIdentity(subject, userPrincipal, roles);
+ return _identityService.newUserIdentity(subject, userPrincipal, roleNames.toArray(new String[0]));
}
return null;
@@ -185,10 +133,10 @@ public abstract class AbstractLoginService extends ContainerLifeCycle implements
if (user.getUserPrincipal() instanceof UserPrincipal)
{
- return fresh.authenticate(((UserPrincipal)user.getUserPrincipal())._credential);
+ return fresh.authenticate(((UserPrincipal)user.getUserPrincipal()));
}
- throw new IllegalStateException("UserPrincipal not KnownUser"); //can't validate
+ throw new IllegalStateException("UserPrincipal not known"); //can't validate
}
@Override
@@ -201,7 +149,6 @@ public abstract class AbstractLoginService extends ContainerLifeCycle implements
public void logout(UserIdentity user)
{
//Override in subclasses
-
}
public boolean isFullValidate()
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java
index c39d7d8d532..846ab8d43a6 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java
@@ -19,20 +19,13 @@
package org.eclipse.jetty.security;
import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-import org.eclipse.jetty.server.UserIdentity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * Properties User Realm.
- *
- * An implementation of UserRealm that stores users and roles in-memory in HashMaps.
- *
- * Typically these maps are populated by calling the load() method or passing a properties resource to the constructor. The format of the properties file is:
- *
+ * An implementation of a LoginService that stores users and roles in-memory in HashMaps.
+ * The source of the users and roles information is a properties file formatted like so:
*
* username: password [,rolename ...]
*
@@ -72,7 +65,7 @@ public class HashLoginService extends AbstractLoginService
}
/**
- * Load realm users from properties file.
+ * Load users from properties file.
*
* The property file maps usernames to password specs followed by an optional comma separated list of role names.
*
@@ -121,41 +114,21 @@ public class HashLoginService extends AbstractLoginService
}
@Override
- protected String[] loadRoleInfo(UserPrincipal user)
+ protected List loadRoleInfo(UserPrincipal user)
{
- UserIdentity id = _userStore.getUserIdentity(user.getName());
- if (id == null)
- return null;
-
- Set roles = id.getSubject().getPrincipals(RolePrincipal.class);
- if (roles == null)
- return null;
-
- List list = roles.stream()
- .map(rolePrincipal -> rolePrincipal.getName())
- .collect(Collectors.toList());
-
- return list.toArray(new String[roles.size()]);
+ return _userStore.getRolePrincipals(user.getName());
}
@Override
protected UserPrincipal loadUserInfo(String userName)
{
- UserIdentity id = _userStore.getUserIdentity(userName);
- if (id != null)
- {
- return (UserPrincipal)id.getUserPrincipal();
- }
-
- return null;
+ return _userStore.getUserPrincipal(userName);
}
@Override
protected void doStart() throws Exception
{
super.doStart();
-
- // can be null so we switch to previous behaviour using PropertyUserStore
if (_userStore == null)
{
if (LOG.isDebugEnabled())
@@ -179,7 +152,6 @@ public class HashLoginService extends AbstractLoginService
}
/**
- * To facilitate testing.
*
* @return true if a UserStore has been created from a config, false if a UserStore was provided.
*/
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/JDBCLoginService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/JDBCLoginService.java
index 828ce13dd12..828089eb959 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/JDBCLoginService.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/JDBCLoginService.java
@@ -18,7 +18,6 @@
package org.eclipse.jetty.security;
-import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
@@ -28,6 +27,7 @@ import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
+import java.util.stream.Collectors;
import jakarta.servlet.ServletRequest;
import org.eclipse.jetty.util.Loader;
@@ -37,17 +37,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * HashMapped User Realm with JDBC as data source.
- * The {@link #login(String, Object, ServletRequest)} method checks the inherited Map for the user. If the user is not
- * found, it will fetch details from the database and populate the inherited
- * Map. It then calls the superclass {@link #login(String, Object, ServletRequest)} method to perform the actual
- * authentication. Periodically (controlled by configuration parameter),
- * internal hashes are cleared. Caching can be disabled by setting cache refresh
- * interval to zero. Uses one database connection that is initialized at
- * startup. Reconnect on failures.
- *
- * An example properties file for configuration is in
- * ${jetty.home}/etc/jdbcRealm.properties
+ * JDBC as a source of user authentication and authorization information.
+ * Uses one database connection that is lazily initialized. Reconnect on failures.
*/
public class JDBCLoginService extends AbstractLoginService
{
@@ -61,16 +52,18 @@ public class JDBCLoginService extends AbstractLoginService
protected String _userTableKey;
protected String _userTablePasswordField;
protected String _roleTableRoleField;
- protected Connection _con;
protected String _userSql;
protected String _roleSql;
+ protected Connection _con;
/**
- * JDBCKnownUser
+ * JDBCUserPrincipal
+ *
+ * A UserPrincipal with extra jdbc key info.
*/
public class JDBCUserPrincipal extends UserPrincipal
{
- int _userKey;
+ final int _userKey;
public JDBCUserPrincipal(String name, Credential credential, int key)
{
@@ -85,25 +78,21 @@ public class JDBCLoginService extends AbstractLoginService
}
public JDBCLoginService()
- throws IOException
{
}
public JDBCLoginService(String name)
- throws IOException
{
setName(name);
}
public JDBCLoginService(String name, String config)
- throws IOException
{
setName(name);
setConfig(config);
}
public JDBCLoginService(String name, IdentityService identityService, String config)
- throws IOException
{
setName(name);
setIdentityService(identityService);
@@ -171,19 +160,12 @@ public class JDBCLoginService extends AbstractLoginService
}
/**
- * (re)Connect to database with parameters setup by loadConfig()
+ * Connect to database with parameters setup by loadConfig()
*/
- public void connectDatabase()
+ public Connection connectDatabase()
+ throws SQLException
{
- try
- {
- Class.forName(_jdbcDriver);
- _con = DriverManager.getConnection(_url, _userName, _password);
- }
- catch (Exception e)
- {
- LOG.warn("UserRealm {} could not connect to database; will try later", getName(), e);
- }
+ return DriverManager.getConnection(_url, _userName, _password);
}
@Override
@@ -192,10 +174,7 @@ public class JDBCLoginService extends AbstractLoginService
try
{
if (null == _con)
- connectDatabase();
-
- if (null == _con)
- throw new SQLException("Can't connect to database");
+ _con = connectDatabase();
try (PreparedStatement stat1 = _con.prepareStatement(_userSql))
{
@@ -214,7 +193,7 @@ public class JDBCLoginService extends AbstractLoginService
}
catch (SQLException e)
{
- LOG.warn("UserRealm {} could not load user information from database", getName(), e);
+ LOG.warn("LoginService {} could not load user {}", getName(), username, e);
closeConnection();
}
@@ -222,17 +201,17 @@ public class JDBCLoginService extends AbstractLoginService
}
@Override
- public String[] loadRoleInfo(UserPrincipal user)
+ public List loadRoleInfo(UserPrincipal user)
{
+ if (user == null)
+ return null;
+
JDBCUserPrincipal jdbcUser = (JDBCUserPrincipal)user;
try
{
if (null == _con)
- connectDatabase();
-
- if (null == _con)
- throw new SQLException("Can't connect to database");
+ _con = connectDatabase();
List roles = new ArrayList();
@@ -242,16 +221,15 @@ public class JDBCLoginService extends AbstractLoginService
try (ResultSet rs2 = stat2.executeQuery())
{
while (rs2.next())
- {
roles.add(rs2.getString(_roleTableRoleField));
- }
- return roles.toArray(new String[roles.size()]);
+
+ return roles.stream().map(RolePrincipal::new).collect(Collectors.toList());
}
}
}
catch (SQLException e)
{
- LOG.warn("UserRealm {} could not load user information from database", getName(), e);
+ LOG.warn("LoginService {} could not load roles for user {}", getName(), user.getName(), e);
closeConnection();
}
@@ -273,7 +251,7 @@ public class JDBCLoginService extends AbstractLoginService
if (_con != null)
{
if (LOG.isDebugEnabled())
- LOG.debug("Closing db connection for JDBCUserRealm");
+ LOG.debug("Closing db connection for JDBCLoginService");
try
{
_con.close();
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java b/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java
index 0fb47ec1698..f692abfef18 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java
@@ -206,7 +206,7 @@ public class PropertyUserStore extends UserStore implements PathWatcher.Listener
@Override
public String toString()
{
- return String.format("%s@%x[users.count=%d,identityService=%s]", getClass().getSimpleName(), hashCode(), getKnownUserIdentities().size(), getIdentityService());
+ return String.format("%s[cfg=%s]", super.toString(), _configPath);
}
protected void loadUsers() throws IOException
@@ -251,7 +251,7 @@ public class PropertyUserStore extends UserStore implements PathWatcher.Listener
}
}
- List currentlyKnownUsers = new ArrayList<>(getKnownUserIdentities().keySet());
+ List currentlyKnownUsers = new ArrayList<>(_users.keySet());
// if its not the initial load then we want to process removed users
if (!_firstLoad)
{
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/RolePrincipal.java b/jetty-security/src/main/java/org/eclipse/jetty/security/RolePrincipal.java
new file mode 100644
index 00000000000..46bcba5b0a4
--- /dev/null
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/RolePrincipal.java
@@ -0,0 +1,52 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
+//
+// This program and the accompanying materials are made available under
+// the terms of the Eclipse Public License 2.0 which is available at
+// https://www.eclipse.org/legal/epl-2.0
+//
+// This Source Code may also be made available under the following
+// Secondary Licenses when the conditions for such availability set
+// forth in the Eclipse Public License, v. 2.0 are satisfied:
+// the Apache License v2.0 which is available at
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+// ========================================================================
+//
+
+package org.eclipse.jetty.security;
+
+import java.io.Serializable;
+import java.security.Principal;
+import javax.security.auth.Subject;
+
+/**
+ * RolePrincipal
+ *
+ * Represents a role. This class can be added to a Subject to represent a role that the
+ * Subject has.
+ *
+ */
+public class RolePrincipal implements Principal, Serializable
+{
+ private static final long serialVersionUID = 2998397924051854402L;
+ private final String _roleName;
+
+ public RolePrincipal(String name)
+ {
+ _roleName = name;
+ }
+
+ @Override
+ public String getName()
+ {
+ return _roleName;
+ }
+
+ public void configureForSubject(Subject subject)
+ {
+ subject.getPrincipals().add(this);
+ }
+}
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/UserPrincipal.java b/jetty-security/src/main/java/org/eclipse/jetty/security/UserPrincipal.java
new file mode 100644
index 00000000000..a4946c1aed2
--- /dev/null
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/UserPrincipal.java
@@ -0,0 +1,92 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
+//
+// This program and the accompanying materials are made available under
+// the terms of the Eclipse Public License 2.0 which is available at
+// https://www.eclipse.org/legal/epl-2.0
+//
+// This Source Code may also be made available under the following
+// Secondary Licenses when the conditions for such availability set
+// forth in the Eclipse Public License, v. 2.0 are satisfied:
+// the Apache License v2.0 which is available at
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+// ========================================================================
+//
+
+package org.eclipse.jetty.security;
+
+import java.io.Serializable;
+import java.security.Principal;
+import javax.security.auth.Subject;
+
+import org.eclipse.jetty.util.security.Credential;
+
+/**
+ * UserPrincipal
+ *
+ * Represents a user with a credential.
+ * Instances of this class can be added to a Subject to
+ * present the user, while the credentials can be added
+ * directly to the Subject.
+ */
+public class UserPrincipal implements Principal, Serializable
+{
+ private static final long serialVersionUID = -6226920753748399662L;
+ private final String _name;
+ protected final Credential _credential;
+
+ public UserPrincipal(String name, Credential credential)
+ {
+ _name = name;
+ _credential = credential;
+ }
+
+ public boolean authenticate(Object credentials)
+ {
+ return _credential != null && _credential.check(credentials);
+ }
+
+ public boolean authenticate(Credential c)
+ {
+ return (_credential != null && c != null && _credential.equals(c));
+ }
+
+ public boolean authenticate(UserPrincipal u)
+ {
+ return (u != null && authenticate(u._credential));
+ }
+
+ public void configureSubject(Subject subject)
+ {
+ if (subject == null)
+ return;
+
+ subject.getPrincipals().add(this);
+ if (_credential != null)
+ subject.getPrivateCredentials().add(_credential);
+ }
+
+ public void deconfigureSubject(Subject subject)
+ {
+ if (subject == null)
+ return;
+ subject.getPrincipals().remove(this);
+ if (_credential != null)
+ subject.getPrivateCredentials().remove(_credential);
+ }
+
+ @Override
+ public String getName()
+ {
+ return _name;
+ }
+
+ @Override
+ public String toString()
+ {
+ return _name;
+ }
+}
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/UserStore.java b/jetty-security/src/main/java/org/eclipse/jetty/security/UserStore.java
index 9efde97029e..6cb78971896 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/UserStore.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/UserStore.java
@@ -18,59 +18,75 @@
package org.eclipse.jetty.security;
-import java.security.Principal;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import javax.security.auth.Subject;
+import java.util.stream.Collectors;
-import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.security.Credential;
/**
- * Base class to store User
+ * Store of user authentication and authorization information.
+ *
*/
public class UserStore extends AbstractLifeCycle
{
- private IdentityService _identityService = new DefaultIdentityService();
- private final Map _knownUserIdentities = new ConcurrentHashMap<>();
+ protected final Map _users = new ConcurrentHashMap<>();
+
+ protected class User
+ {
+ protected UserPrincipal _userPrincipal;
+ protected List _rolePrincipals = Collections.emptyList();
+
+ protected User(String username, Credential credential, String[] roles)
+ {
+ _userPrincipal = new UserPrincipal(username, credential);
+ _rolePrincipals = Collections.emptyList();
+
+ if (roles != null)
+ _rolePrincipals = Arrays.stream(roles).map(RolePrincipal::new).collect(Collectors.toList());
+ }
+
+ protected UserPrincipal getUserPrincipal()
+ {
+ return _userPrincipal;
+ }
+
+ protected List getRolePrincipals()
+ {
+ return _rolePrincipals;
+ }
+ }
+
public void addUser(String username, Credential credential, String[] roles)
{
- Principal userPrincipal = new AbstractLoginService.UserPrincipal(username, credential);
- Subject subject = new Subject();
- subject.getPrincipals().add(userPrincipal);
- subject.getPrivateCredentials().add(credential);
-
- if (roles != null)
- {
- for (String role : roles)
- {
- subject.getPrincipals().add(new AbstractLoginService.RolePrincipal(role));
- }
- }
-
- subject.setReadOnly();
- _knownUserIdentities.put(username, _identityService.newUserIdentity(subject, userPrincipal, roles));
+ _users.put(username, new User(username, credential, roles));
}
public void removeUser(String username)
{
- _knownUserIdentities.remove(username);
+ _users.remove(username);
+ }
+
+ public UserPrincipal getUserPrincipal(String username)
+ {
+ User user = _users.get(username);
+ return (user == null ? null : user.getUserPrincipal());
+ }
+
+ public List getRolePrincipals(String username)
+ {
+ User user = _users.get(username);
+ return (user == null ? null : user.getRolePrincipals());
}
- public UserIdentity getUserIdentity(String userName)
+ @Override
+ public String toString()
{
- return _knownUserIdentities.get(userName);
- }
-
- public IdentityService getIdentityService()
- {
- return _identityService;
- }
-
- public Map getKnownUserIdentities()
- {
- return _knownUserIdentities;
+ return String.format("%s@%x[users.count=%d]", getClass().getSimpleName(), hashCode(), _users.size());
}
}
diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/PropertyUserStoreTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/PropertyUserStoreTest.java
index 9feba87321b..9651b81bcf0 100644
--- a/jetty-security/src/test/java/org/eclipse/jetty/security/PropertyUserStoreTest.java
+++ b/jetty-security/src/test/java/org/eclipse/jetty/security/PropertyUserStoreTest.java
@@ -191,9 +191,9 @@ public class PropertyUserStoreTest
store.start();
- assertThat("Failed to retrieve UserIdentity directly from PropertyUserStore", store.getUserIdentity("tom"), notNullValue());
- assertThat("Failed to retrieve UserIdentity directly from PropertyUserStore", store.getUserIdentity("dick"), notNullValue());
- assertThat("Failed to retrieve UserIdentity directly from PropertyUserStore", store.getUserIdentity("harry"), notNullValue());
+ assertThat("Failed to retrieve user directly from PropertyUserStore", store.getUserPrincipal("tom"), notNullValue());
+ assertThat("Failed to retrieve user directly from PropertyUserStore", store.getUserPrincipal("dick"), notNullValue());
+ assertThat("Failed to retrieve user directly from PropertyUserStore", store.getUserPrincipal("harry"), notNullValue());
userCount.assertThatCount(is(3));
userCount.awaitCount(3);
}
@@ -224,12 +224,12 @@ public class PropertyUserStoreTest
store.start();
- assertThat("Failed to retrieve UserIdentity directly from PropertyUserStore", //
- store.getUserIdentity("tom"), notNullValue());
- assertThat("Failed to retrieve UserIdentity directly from PropertyUserStore", //
- store.getUserIdentity("dick"), notNullValue());
- assertThat("Failed to retrieve UserIdentity directly from PropertyUserStore", //
- store.getUserIdentity("harry"), notNullValue());
+ assertThat("Failed to retrieve user directly from PropertyUserStore", //
+ store.getUserPrincipal("tom"), notNullValue());
+ assertThat("Failed to retrieve user directly from PropertyUserStore", //
+ store.getUserPrincipal("dick"), notNullValue());
+ assertThat("Failed to retrieve user directly from PropertyUserStore", //
+ store.getUserPrincipal("harry"), notNullValue());
userCount.assertThatCount(is(3));
userCount.awaitCount(3);
}
@@ -264,7 +264,7 @@ public class PropertyUserStoreTest
addAdditionalUser(usersFile, "skip: skip, roleA\n");
userCount.awaitCount(4);
assertThat(loadCount.get(), is(2));
- assertThat(store.getUserIdentity("skip"), notNullValue());
+ assertThat(store.getUserPrincipal("skip"), notNullValue());
userCount.assertThatCount(is(4));
userCount.assertThatUsers(hasItem("skip"));
diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/TestLoginService.java b/jetty-security/src/test/java/org/eclipse/jetty/security/TestLoginService.java
index d54b1dd8dc1..00395840df6 100644
--- a/jetty-security/src/test/java/org/eclipse/jetty/security/TestLoginService.java
+++ b/jetty-security/src/test/java/org/eclipse/jetty/security/TestLoginService.java
@@ -44,26 +44,14 @@ public class TestLoginService extends AbstractLoginService
}
@Override
- protected String[] loadRoleInfo(UserPrincipal user)
+ protected List loadRoleInfo(UserPrincipal user)
{
- UserIdentity userIdentity = userStore.getUserIdentity(user.getName());
- Set roles = userIdentity.getSubject().getPrincipals(RolePrincipal.class);
- if (roles == null)
- return null;
-
- List list = new ArrayList<>();
- for (RolePrincipal r : roles)
- {
- list.add(r.getName());
- }
-
- return list.toArray(new String[roles.size()]);
+ return userStore.getRolePrincipals(user.getName());
}
@Override
protected UserPrincipal loadUserInfo(String username)
{
- UserIdentity userIdentity = userStore.getUserIdentity(username);
- return userIdentity == null ? null : (UserPrincipal)userIdentity.getUserPrincipal();
+ return userStore.getUserPrincipal(username);
}
}
diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/UserStoreTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/UserStoreTest.java
index fdd14c2d825..5fef57475df 100644
--- a/jetty-security/src/test/java/org/eclipse/jetty/security/UserStoreTest.java
+++ b/jetty-security/src/test/java/org/eclipse/jetty/security/UserStoreTest.java
@@ -19,10 +19,7 @@
package org.eclipse.jetty.security;
import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.security.Credential;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -44,30 +41,21 @@ public class UserStoreTest
@Test
public void addUser()
{
- this.userStore.addUser("foo", Credential.getCredential("beer"), new String[]{"pub"});
- assertEquals(1, this.userStore.getKnownUserIdentities().size());
- UserIdentity userIdentity = this.userStore.getUserIdentity("foo");
- assertNotNull(userIdentity);
- assertEquals("foo", userIdentity.getUserPrincipal().getName());
- Set
- roles = userIdentity.getSubject().getPrincipals(AbstractLoginService.RolePrincipal.class);
- List list = roles.stream()
- .map(rolePrincipal -> rolePrincipal.getName())
- .collect(Collectors.toList());
- assertEquals(1, list.size());
- assertEquals("pub", list.get(0));
+ userStore.addUser("foo", Credential.getCredential("beer"), new String[]{"pub"});
+ assertNotNull(userStore.getUserPrincipal("foo"));
+
+ List rps = userStore.getRolePrincipals("foo");
+ assertNotNull(rps);
+ assertNotNull(rps.get(0));
+ assertEquals("pub", rps.get(0).getName());
}
@Test
public void removeUser()
{
this.userStore.addUser("foo", Credential.getCredential("beer"), new String[]{"pub"});
- assertEquals(1, this.userStore.getKnownUserIdentities().size());
- UserIdentity userIdentity = this.userStore.getUserIdentity("foo");
- assertNotNull(userIdentity);
- assertEquals("foo", userIdentity.getUserPrincipal().getName());
+ assertNotNull(userStore.getUserPrincipal("foo"));
userStore.removeUser("foo");
- userIdentity = this.userStore.getUserIdentity("foo");
- assertNull(userIdentity);
+ assertNull(userStore.getUserPrincipal("foo"));
}
}
diff --git a/tests/test-integration/src/test/java/org/eclipse/jetty/test/DigestPostTest.java b/tests/test-integration/src/test/java/org/eclipse/jetty/test/DigestPostTest.java
index f69b273b8c2..9192394a540 100644
--- a/tests/test-integration/src/test/java/org/eclipse/jetty/test/DigestPostTest.java
+++ b/tests/test-integration/src/test/java/org/eclipse/jetty/test/DigestPostTest.java
@@ -24,10 +24,13 @@ import java.net.Socket;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
@@ -43,6 +46,8 @@ import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.security.AbstractLoginService;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
+import org.eclipse.jetty.security.RolePrincipal;
+import org.eclipse.jetty.security.UserPrincipal;
import org.eclipse.jetty.security.authentication.DigestAuthenticator;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.NetworkConnector;
@@ -85,7 +90,7 @@ public class DigestPostTest
public static class TestLoginService extends AbstractLoginService
{
protected Map users = new HashMap<>();
- protected Map roles = new HashMap<>();
+ protected Map> roles = new HashMap<>();
public TestLoginService(String name)
{
@@ -96,11 +101,12 @@ public class DigestPostTest
{
UserPrincipal userPrincipal = new UserPrincipal(username, credential);
users.put(username, userPrincipal);
- roles.put(username, rolenames);
+ if (rolenames != null)
+ roles.put(username, Arrays.stream(rolenames).map(RolePrincipal::new).collect(Collectors.toList()));
}
@Override
- protected String[] loadRoleInfo(UserPrincipal user)
+ protected List loadRoleInfo(UserPrincipal user)
{
return roles.get(user.getName());
}