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 0bcdd54c171..552b4fab4ca 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 @@ -289,6 +289,7 @@ public abstract class AbstractLoginModule implements LoginModule public boolean logout() throws LoginException { this.currentUser.unsetJAASInfo(this.subject); + this.currentUser = null; return true; } 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 3560f2b57bd..8750aaf19ae 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 @@ -48,6 +48,8 @@ public class PropertyFileLoginModule extends AbstractLoginModule private int _refreshInterval = 0; private String _filename = DEFAULT_FILENAME; + + /** * Read contents of the configured property file. * @@ -73,7 +75,6 @@ public class PropertyFileLoginModule extends AbstractLoginModule { PropertyUserStore propertyUserStore = new PropertyUserStore(); propertyUserStore.setConfig(_filename); - propertyUserStore.setRefreshInterval(_refreshInterval); PropertyUserStore prev = _propertyUserStores.putIfAbsent(_filename, propertyUserStore); if (prev == null) 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 4bc51cb7824..25eb1b8bc95 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 @@ -22,14 +22,16 @@ import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.assertThat; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.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.HashLoginService; import org.eclipse.jetty.server.LocalConnector; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; @@ -38,6 +40,7 @@ import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.util.B64Code; import org.eclipse.jetty.util.security.Constraint; +import org.eclipse.jetty.util.security.Credential; import org.eclipse.jetty.util.security.Password; import org.hamcrest.Matchers; import org.junit.After; @@ -48,6 +51,43 @@ public class JaspiTest { Server _server; LocalConnector _connector; + public class TestLoginService extends AbstractLoginService + { + protected Map _users = new HashMap<>(); + protected Map _roles = new HashMap(); + + + + public TestLoginService(String name) + { + setName(name); + } + + public void putUser (String username, Credential credential, String[] roles) + { + UserPrincipal userPrincipal = new UserPrincipal(username,credential); + _users.put(username, userPrincipal); + _roles.put(username, roles); + } + + /** + * @see org.eclipse.jetty.security.AbstractLoginService#loadRoleInfo(org.eclipse.jetty.security.AbstractLoginService.UserPrincipal) + */ + @Override + protected String[] loadRoleInfo(UserPrincipal user) + { + return _roles.get(user.getName()); + } + + /** + * @see org.eclipse.jetty.security.AbstractLoginService#loadUserInfo(java.lang.String) + */ + @Override + protected UserPrincipal loadUserInfo(String username) + { + return _users.get(username); + } + } @Before public void before() throws Exception @@ -60,7 +100,7 @@ public class JaspiTest ContextHandlerCollection contexts = new ContextHandlerCollection(); _server.setHandler(contexts); - HashLoginService loginService = new HashLoginService("TestRealm"); + TestLoginService loginService = new TestLoginService("TestRealm"); loginService.putUser("user",new Password("password"),new String[]{"users"}); loginService.putUser("admin",new Password("secret"),new String[]{"users","admins"}); _server.addBean(loginService); diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-testrealm.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-testrealm.xml index 4c8cb533cc5..056e0c251bf 100644 --- a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-testrealm.xml +++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-testrealm.xml @@ -13,7 +13,6 @@ Test Realm realm.properties - 0 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 aa61b57a0e9..4d06aee05b3 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 @@ -32,14 +32,12 @@ import java.util.Locale; import javax.naming.InitialContext; import javax.naming.NameNotFoundException; import javax.naming.NamingException; -import javax.servlet.ServletRequest; 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.MappedLoginService; import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.UserIdentity; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.security.Credential; @@ -51,7 +49,7 @@ import org.eclipse.jetty.util.security.Credential; * Obtain user/password/role information from a database * via jndi DataSource. */ -public class DataSourceLoginService extends MappedLoginService +public class DataSourceLoginService extends AbstractLoginService { private static final Logger LOG = Log.getLogger(DataSourceLoginService.class); @@ -68,8 +66,6 @@ public class DataSourceLoginService extends MappedLoginService private String _userRoleTableName = "user_roles"; private String _userRoleTableUserKey = "user_id"; private String _userRoleTableRoleKey = "role_id"; - private int _cacheMs = 30000; - private long _lastPurge = 0; private String _userSql; private String _roleSql; private boolean _createTables = false; @@ -80,7 +76,7 @@ public class DataSourceLoginService extends MappedLoginService * * */ - public class DBUser extends KnownUser + public class DBUserPrincipal extends UserPrincipal { private int _key; @@ -88,7 +84,7 @@ public class DataSourceLoginService extends MappedLoginService * @param name * @param credential */ - public DBUser(String name, Credential credential, int key) + public DBUserPrincipal(String name, Credential credential, int key) { super(name, credential); _key = key; @@ -292,81 +288,14 @@ public class DataSourceLoginService extends MappedLoginService _userRoleTableRoleKey = roleTableRoleKey; } - /* ------------------------------------------------------------ */ - public void setCacheMs (int ms) - { - _cacheMs=ms; - } - - /* ------------------------------------------------------------ */ - public int getCacheMs () - { - return _cacheMs; - } - - /* ------------------------------------------------------------ */ - @Override - protected void loadUsers() - { - } - - + /* ------------------------------------------------------------ */ - /** Load user's info from database. - * - * @param userName the user name - */ - @Deprecated - protected UserIdentity loadUser (String userName) - { - try - { - try (Connection connection = getConnection(); - PreparedStatement statement1 = connection.prepareStatement(_userSql)) - { - statement1.setObject(1, userName); - try (ResultSet rs1 = statement1.executeQuery()) - { - if (rs1.next()) - { - int key = rs1.getInt(_userTableKey); - String credentials = rs1.getString(_userTablePasswordField); - - List roles = new ArrayList(); - try (PreparedStatement statement2 = connection.prepareStatement(_roleSql)) - { - statement2.setInt(1, key); - try (ResultSet rs2 = statement2.executeQuery()) - { - while (rs2.next()) - { - roles.add(rs2.getString(_roleTableRoleField)); - } - } - } - return putUser(userName, Credential.getCredential(credentials), roles.toArray(new String[roles.size()])); - } - } - } - } - catch (NamingException e) - { - LOG.warn("No datasource for "+_jndiName, e); - } - catch (SQLException e) - { - LOG.warn("Problem loading user info for "+userName, e); - } - return null; - } - - /** * @see org.eclipse.jetty.security.MappedLoginService#loadUserInfo(java.lang.String) * @Override */ - public KnownUser loadUserInfo (String username) + public UserPrincipal loadUserInfo (String username) { try { @@ -381,7 +310,7 @@ public class DataSourceLoginService extends MappedLoginService int key = rs1.getInt(_userTableKey); String credentials = rs1.getString(_userTablePasswordField); - return new DBUser(username, Credential.getCredential(credentials), key); + return new DBUserPrincipal(username, Credential.getCredential(credentials), key); } } } @@ -397,13 +326,15 @@ public class DataSourceLoginService extends MappedLoginService return null; } + + /* ------------------------------------------------------------ */ /** - * @see org.eclipse.jetty.security.MappedLoginService#loadRoleInfo(org.eclipse.jetty.security.MappedLoginService.KnownUser) + * @see org.eclipse.jetty.security.MappedLoginService#loadRoleInfo(org.eclipse.jetty.security.UserPrincipal.KnownUser) * @Override */ - public String[] loadRoleInfo (KnownUser user) + public String[] loadRoleInfo (UserPrincipal user) { - DBUser dbuser = (DBUser)user; + DBUserPrincipal dbuser = (DBUserPrincipal)user; try { @@ -440,19 +371,7 @@ public class DataSourceLoginService extends MappedLoginService - /* ------------------------------------------------------------ */ - @Override - public UserIdentity login(String username, Object credentials, ServletRequest request) - { - long now = System.currentTimeMillis(); - if (now - _lastPurge > _cacheMs || _cacheMs == 0) - { - _users.clear(); - _lastPurge = now; - } - return super.login(username,credentials, request); - } /* ------------------------------------------------------------ */ /** @@ -509,6 +428,11 @@ public class DataSourceLoginService extends MappedLoginService + /* ------------------------------------------------------------ */ + /** + * @throws NamingException + * @throws SQLException + */ private void prepareTables() throws NamingException, SQLException { @@ -610,6 +534,12 @@ public class DataSourceLoginService extends MappedLoginService } + /* ------------------------------------------------------------ */ + /** + * @return + * @throws NamingException + * @throws SQLException + */ private Connection getConnection () throws NamingException, SQLException { diff --git a/jetty-rewrite/src/test/resources/org.mortbay.jetty.rewrite.handler/jetty-rewrite.xml b/jetty-rewrite/src/test/resources/org.mortbay.jetty.rewrite.handler/jetty-rewrite.xml index 9ac510991d2..1afc8030966 100644 --- a/jetty-rewrite/src/test/resources/org.mortbay.jetty.rewrite.handler/jetty-rewrite.xml +++ b/jetty-rewrite/src/test/resources/org.mortbay.jetty.rewrite.handler/jetty-rewrite.xml @@ -240,7 +240,6 @@ Test Realm /etc/realm.properties - 0 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 new file mode 100644 index 00000000000..c38a195aa52 --- /dev/null +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/AbstractLoginService.java @@ -0,0 +1,270 @@ +// +// ======================================================================== +// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + + +package org.eclipse.jetty.security; + +import java.io.Serializable; +import java.security.Principal; + +import javax.security.auth.Subject; +import javax.servlet.ServletRequest; + + +import org.eclipse.jetty.server.UserIdentity; +import org.eclipse.jetty.util.component.AbstractLifeCycle; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.util.security.Credential; + +/** + * AbstractLoginService + * + * + */ +public abstract class AbstractLoginService extends AbstractLifeCycle implements LoginService +{ + private static final Logger LOG = Log.getLogger(AbstractLoginService.class); + + protected IdentityService _identityService=new DefaultIdentityService(); + 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; + } + 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)); + } + + /* ------------------------------------------------------------ */ + public String getName() + { + return _name; + } + + + + /* -------------------------------------------------------- */ + @Override + public String toString() + { + return _name; + } + } + + + + + /* ------------------------------------------------------------ */ + protected abstract String[] loadRoleInfo (UserPrincipal user); + + + /* ------------------------------------------------------------ */ + protected abstract UserPrincipal loadUserInfo (String username); + + + + + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.security.LoginService#getName() + */ + @Override + public String getName() + { + return _name; + } + + /* ------------------------------------------------------------ */ + /** Set the identityService. + * @param identityService the identityService to set + */ + public void setIdentityService(IdentityService identityService) + { + if (isRunning()) + throw new IllegalStateException("Running"); + _identityService = identityService; + } + + /* ------------------------------------------------------------ */ + /** Set the name. + * @param name the name to set + */ + public void setName(String name) + { + if (isRunning()) + throw new IllegalStateException("Running"); + _name = name; + } + + /* ------------------------------------------------------------ */ + @Override + public String toString() + { + return this.getClass().getSimpleName()+"["+_name+"]"; + } + + + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.security.LoginService#login(java.lang.String, java.lang.Object, javax.servlet.ServletRequest) + */ + @Override + public UserIdentity login(String username, Object credentials, ServletRequest request) + { + if (username == null) + return null; + + UserPrincipal userPrincipal = loadUserInfo(username); + if (userPrincipal.authenticate(credentials)) + { + //safe to load the roles + String[] roles = loadRoleInfo(userPrincipal); + + Subject subject = new Subject(); + subject.getPrincipals().add(userPrincipal); + subject.getPrivateCredentials().add(userPrincipal._credential); + if (roles!=null) + for (String role : roles) + subject.getPrincipals().add(new RolePrincipal(role)); + subject.setReadOnly(); + return _identityService.newUserIdentity(subject,userPrincipal,roles); + } + + return null; + + } + + + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.security.LoginService#validate(org.eclipse.jetty.server.UserIdentity) + */ + @Override + public boolean validate(UserIdentity user) + { + if (!isFullValidate()) + return true; //if we have a user identity it must be valid + + //Do a full validation back against the user store + UserPrincipal fresh = loadUserInfo(user.getUserPrincipal().getName()); + if (fresh == null) + return false; //user no longer exists + + if (user.getUserPrincipal() instanceof UserPrincipal) + { + System.err.println("VALIDATING user "+fresh.getName()); + return fresh.authenticate(((UserPrincipal)user.getUserPrincipal())._credential); + } + + throw new IllegalStateException("UserPrincipal not KnownUser"); //can't validate + } + + + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.security.LoginService#getIdentityService() + */ + @Override + public IdentityService getIdentityService() + { + return _identityService; + } + + + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.security.LoginService#logout(org.eclipse.jetty.server.UserIdentity) + */ + @Override + public void logout(UserIdentity user) + { + //Override in subclasses + + } + + /* ------------------------------------------------------------ */ + /** + * @return + */ + public boolean isFullValidate() + { + return _fullValidate; + } + + /* ------------------------------------------------------------ */ + /** + * @param fullValidate + */ + public void setFullValidate(boolean fullValidate) + { + _fullValidate = fullValidate; + } + +} 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 659083b7cf6..f0774a707d4 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 @@ -23,7 +23,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; -import org.eclipse.jetty.security.MappedLoginService.KnownUser; import org.eclipse.jetty.security.PropertyUserStore.UserListener; import org.eclipse.jetty.server.UserIdentity; import org.eclipse.jetty.util.Scanner; @@ -49,45 +48,17 @@ import org.eclipse.jetty.util.security.Credential; *

* If DIGEST Authentication is used, the password must be in a recoverable format, either plain text or OBF:. */ -public class HashLoginService extends MappedLoginService implements UserListener +public class HashLoginService extends AbstractLoginService { private static final Logger LOG = Log.getLogger(HashLoginService.class); - private PropertyUserStore _propertyUserStore; - private String _config; - private Resource _configResource; - private Scanner _scanner; - private boolean hotReload = false; // default is not to reload + protected PropertyUserStore _propertyUserStore; + protected String _config; + protected Resource _configResource; + protected boolean hotReload = false; // default is not to reload - public class HashKnownUser extends KnownUser - { - String[] _roles; - - /** - * @param name - * @param credential - */ - public HashKnownUser(String name, Credential credential) - { - super(name, credential); - } - - - - public void setRoles (String[] roles) - { - _roles = roles; - } - - public String[] getRoles() - { - return _roles; - } - } - - /* ------------------------------------------------------------ */ public HashLoginService() @@ -161,46 +132,11 @@ public class HashLoginService extends MappedLoginService implements UserListener this.hotReload = enable; } - /* ------------------------------------------------------------ */ - /** - * sets the refresh interval (in seconds) - * @param sec the refresh interval - * @deprecated use {@link #setHotReload(boolean)} instead - */ - @Deprecated - public void setRefreshInterval(int sec) - { - } - - /* ------------------------------------------------------------ */ - /** - * @return refresh interval in seconds for how often the properties file should be checked for changes - * @deprecated use {@link #isHotReload()} instead - */ - @Deprecated - public int getRefreshInterval() - { - return (hotReload)?1:0; - } + /* ------------------------------------------------------------ */ @Override - protected UserIdentity loadUser(String username) - { - return null; - } - - /* ------------------------------------------------------------ */ - @Override - public void loadUsers() throws IOException - { - // TODO: Consider refactoring MappedLoginService to not have to override with unused methods - } - - - - @Override - protected String[] loadRoleInfo(KnownUser user) + protected String[] loadRoleInfo(UserPrincipal user) { UserIdentity id = _propertyUserStore.getUserIdentity(user.getName()); if (id == null) @@ -218,13 +154,17 @@ public class HashLoginService extends MappedLoginService implements UserListener return list.toArray(new String[roles.size()]); } + + + + /* ------------------------------------------------------------ */ @Override - protected KnownUser loadUserInfo(String userName) + protected UserPrincipal loadUserInfo(String userName) { UserIdentity id = _propertyUserStore.getUserIdentity(userName); if (id != null) { - return (KnownUser)id.getUserPrincipal(); + return (UserPrincipal)id.getUserPrincipal(); } return null; @@ -249,7 +189,6 @@ public class HashLoginService extends MappedLoginService implements UserListener _propertyUserStore = new PropertyUserStore(); _propertyUserStore.setHotReload(hotReload); _propertyUserStore.setConfigPath(_config); - _propertyUserStore.registerUserListener(this); _propertyUserStore.start(); } } @@ -262,28 +201,5 @@ public class HashLoginService extends MappedLoginService implements UserListener protected void doStop() throws Exception { super.doStop(); - if (_scanner != null) - _scanner.stop(); - _scanner = null; - } - - /* ------------------------------------------------------------ */ - @Override - public void update(String userName, Credential credential, String[] roleArray) - { - if (LOG.isDebugEnabled()) - LOG.debug("update: " + userName + " Roles: " + roleArray.length); - //TODO need to remove and replace the authenticated user? - } - - - - /* ------------------------------------------------------------ */ - @Override - public void remove(String userName) - { - if (LOG.isDebugEnabled()) - LOG.debug("remove: " + userName); - removeUser(userName); } } 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 4294b74ef52..09b5df95126 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 @@ -59,7 +59,7 @@ import org.eclipse.jetty.util.security.Credential; * */ -public class JDBCLoginService extends MappedLoginService +public class JDBCLoginService extends AbstractLoginService { private static final Logger LOG = Log.getLogger(JDBCLoginService.class); @@ -71,8 +71,6 @@ public class JDBCLoginService extends MappedLoginService protected String _userTableKey; protected String _userTablePasswordField; protected String _roleTableRoleField; - protected int _cacheTime; - protected long _lastHashPurge; protected Connection _con; protected String _userSql; protected String _roleSql; @@ -83,7 +81,7 @@ public class JDBCLoginService extends MappedLoginService * * */ - public class JDBCKnownUser extends KnownUser + public class JDBCUserPrincipal extends UserPrincipal { int _userKey; @@ -91,7 +89,7 @@ public class JDBCLoginService extends MappedLoginService * @param name * @param credential */ - public JDBCKnownUser(String name, Credential credential, int key) + public JDBCUserPrincipal(String name, Credential credential, int key) { super(name, credential); _userKey = key; @@ -162,20 +160,18 @@ public class JDBCLoginService extends MappedLoginService String _userRoleTable = properties.getProperty("userroletable"); String _userRoleTableUserKey = properties.getProperty("userroletableuserkey"); String _userRoleTableRoleKey = properties.getProperty("userroletablerolekey"); - _cacheTime = new Integer(properties.getProperty("cachetime")); + if (_jdbcDriver == null || _jdbcDriver.equals("") || _url == null || _url.equals("") || _userName == null || _userName.equals("") - || _password == null - || _cacheTime < 0) + || _password == null) { LOG.warn("UserRealm " + getName() + " has not been properly configured"); } - _cacheTime *= 1000; - _lastHashPurge = 0; + _userSql = "select " + _userTableKey + "," + _userTablePasswordField + " from " + _userTable + " where " + _userTableUserField + " = ?"; _roleSql = "select r." + _roleTableRoleField + " from " @@ -235,80 +231,15 @@ public class JDBCLoginService extends MappedLoginService } } - /* ------------------------------------------------------------ */ - @Override - public UserIdentity login(String username, Object credentials, ServletRequest request) - { - long now = System.currentTimeMillis(); - if (now - _lastHashPurge > _cacheTime || _cacheTime == 0) - { - _users.clear(); - _lastHashPurge = now; - closeConnection(); - } - - return super.login(username,credentials, request); - } - - /* ------------------------------------------------------------ */ - @Override - protected void loadUsers() - { - } + + /* ------------------------------------------------------------ */ - @Deprecated - protected UserIdentity loadUser(String username) - { - try - { - if (null == _con) - connectDatabase(); - - if (null == _con) - throw new SQLException("Can't connect to database"); - - try (PreparedStatement stat1 = _con.prepareStatement(_userSql)) - { - stat1.setObject(1, username); - try (ResultSet rs1 = stat1.executeQuery()) - { - if (rs1.next()) - { - int key = rs1.getInt(_userTableKey); - String credentials = rs1.getString(_userTablePasswordField); - - - List roles = new ArrayList(); - - try (PreparedStatement stat2 = _con.prepareStatement(_roleSql)) - { - stat2.setInt(1, key); - try (ResultSet rs2 = stat2.executeQuery()) - { - while (rs2.next()) - roles.add(rs2.getString(_roleTableRoleField)); - } - } - return putUser(username, Credential.getCredential(credentials), roles.toArray(new String[roles.size()])); - } - } - } - } - catch (SQLException e) - { - LOG.warn("UserRealm " + getName() + " could not load user information from database", e); - closeConnection(); - } - return null; - } - - /** * @see org.eclipse.jetty.security.MappedLoginService#loadUserInfo(java.lang.String) * @Override */ - public KnownUser loadUserInfo (String username) + public UserPrincipal loadUserInfo (String username) { try { @@ -328,7 +259,7 @@ public class JDBCLoginService extends MappedLoginService int key = rs1.getInt(_userTableKey); String credentials = rs1.getString(_userTablePasswordField); - return new JDBCKnownUser (username, Credential.getCredential(credentials), key); + return new JDBCUserPrincipal (username, Credential.getCredential(credentials), key); } } } @@ -343,14 +274,14 @@ public class JDBCLoginService extends MappedLoginService } - + /* ------------------------------------------------------------ */ /** - * @see org.eclipse.jetty.security.MappedLoginService#loadRoleInfo(org.eclipse.jetty.security.MappedLoginService.KnownUser) + * @see org.eclipse.jetty.security.MappedLoginService#loadRoleInfo(org.eclipse.jetty.security.UserPrincipal.KnownUser) * @Override */ - public String[] loadRoleInfo (KnownUser user) + public String[] loadRoleInfo (UserPrincipal user) { - JDBCKnownUser jdbcUser = (JDBCKnownUser)user; + JDBCUserPrincipal jdbcUser = (JDBCUserPrincipal)user; try { @@ -385,7 +316,19 @@ public class JDBCLoginService extends MappedLoginService + + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop() + */ + @Override + protected void doStop() throws Exception + { + closeConnection(); + super.doStop(); + } + /* ------------------------------------------------------------ */ /** * Close an existing connection */ diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/MappedLoginService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/MappedLoginService.java deleted file mode 100644 index 310a4db8bc2..00000000000 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/MappedLoginService.java +++ /dev/null @@ -1,375 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - - -package org.eclipse.jetty.security; - -import java.io.IOException; -import java.io.Serializable; -import java.security.Principal; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import javax.security.auth.Subject; -import javax.servlet.ServletRequest; - -import org.eclipse.jetty.server.UserIdentity; -import org.eclipse.jetty.util.component.AbstractLifeCycle; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.util.security.Credential; - - - -/* ------------------------------------------------------------ */ -/** - * A login service that keeps UserIdentities in a concurrent map - * either as the source or a cache of the users. - * - */ -public abstract class MappedLoginService extends AbstractLifeCycle implements LoginService -{ - private static final Logger LOG = Log.getLogger(MappedLoginService.class); - - protected IdentityService _identityService=new DefaultIdentityService(); - protected String _name; - protected final ConcurrentMap _users=new ConcurrentHashMap(); - - /* ------------------------------------------------------------ */ - protected MappedLoginService() - { - } - - /* ------------------------------------------------------------ */ - /** Get the name. - * @return the name - */ - public String getName() - { - return _name; - } - - /* ------------------------------------------------------------ */ - /** Get the identityService. - * @return the identityService - */ - public IdentityService getIdentityService() - { - return _identityService; - } - - /* ------------------------------------------------------------ */ - /** Get the users. - * @return the users - */ - public ConcurrentMap getUsers() - { - return _users; - } - - /* ------------------------------------------------------------ */ - /** Set the identityService. - * @param identityService the identityService to set - */ - public void setIdentityService(IdentityService identityService) - { - if (isRunning()) - throw new IllegalStateException("Running"); - _identityService = identityService; - } - - /* ------------------------------------------------------------ */ - /** Set the name. - * @param name the name to set - */ - public void setName(String name) - { - if (isRunning()) - throw new IllegalStateException("Running"); - _name = name; - } - - /* ------------------------------------------------------------ */ - /** Set the users. - * @param users the users to set - */ - public void setUsers(Map users) - { - if (isRunning()) - throw new IllegalStateException("Running"); - _users.clear(); - _users.putAll(users); - } - - /* ------------------------------------------------------------ */ - /** - * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart() - */ - @Override - protected void doStart() throws Exception - { - loadUsers(); - super.doStart(); - } - - /* ------------------------------------------------------------ */ - @Override - protected void doStop() throws Exception - { - super.doStop(); - } - - /* ------------------------------------------------------------ */ - public void logout(UserIdentity identity) - { - LOG.debug("logout {}",identity); - - //TODO should remove the user????? - } - - /* ------------------------------------------------------------ */ - @Override - public String toString() - { - return this.getClass().getSimpleName()+"["+_name+"]"; - } - - /* ------------------------------------------------------------ */ - /** Put user into realm. - * Called by implementations to put the user data loaded from - * file/db etc into the user structure. - * @param userName User name - * @param info a UserIdentity instance, or a String password or Credential instance - * @return User instance - */ - protected synchronized UserIdentity putUser(String userName, Object info) - { - final UserIdentity identity; - if (info instanceof UserIdentity) - identity=(UserIdentity)info; - else - { - Credential credential = (info instanceof Credential)?(Credential)info:Credential.getCredential(info.toString()); - - Principal userPrincipal = new KnownUser(userName,credential); - Subject subject = new Subject(); - subject.getPrincipals().add(userPrincipal); - subject.getPrivateCredentials().add(credential); - subject.setReadOnly(); - identity=_identityService.newUserIdentity(subject,userPrincipal,IdentityService.NO_ROLES); - } - - _users.put(userName,identity); - return identity; - } - - /* ------------------------------------------------------------ */ - /** Put user into realm. - * @param userName The user to add - * @param credential The users Credentials - * @param roles The users roles - * @return UserIdentity - */ - public synchronized UserIdentity putUser(String userName, Credential credential, String[] roles) - { - Principal userPrincipal = new KnownUser(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 RolePrincipal(role)); - - subject.setReadOnly(); - UserIdentity identity=_identityService.newUserIdentity(subject,userPrincipal,roles); - _users.put(userName,identity); - return identity; - } - - - - - public synchronized UserIdentity putUser (KnownUser userPrincipal, String[] roles) - { - Subject subject = new Subject(); - subject.getPrincipals().add(userPrincipal); - subject.getPrivateCredentials().add(userPrincipal._credential); - if (roles!=null) - for (String role : roles) - subject.getPrincipals().add(new RolePrincipal(role)); - subject.setReadOnly(); - UserIdentity identity=_identityService.newUserIdentity(subject,userPrincipal,roles); - _users.put(userPrincipal._name,identity); - return identity; - } - - - /* ------------------------------------------------------------ */ - public void removeUser(String username) - { - _users.remove(username); - } - - /* ------------------------------------------------------------ */ - /** - * @see org.eclipse.jetty.security.LoginService#login(java.lang.String, java.lang.Object, ServletRequest) - */ - public UserIdentity login(String username, Object credentials, ServletRequest request) - { - if (username == null) - return null; - - UserIdentity user = _users.get(username); - - if (user==null) - { - KnownUser userPrincipal = loadUserInfo(username); - if (userPrincipal.authenticate(credentials)) - { - //safe to load the roles - String[] roles = loadRoleInfo(userPrincipal); - user = putUser(userPrincipal, roles); - return user; - } - } - else - { - UserPrincipal principal = (UserPrincipal)user.getUserPrincipal(); - if (principal.authenticate(credentials)) - return user; - } - return null; - } - - /* ------------------------------------------------------------ */ - public boolean validate(UserIdentity user) - { - if (_users.containsKey(user.getUserPrincipal().getName())) - return true; - - if (loadUser(user.getUserPrincipal().getName())!=null) - return true; - - return false; - } - /* ------------------------------------------------------------ */ - protected abstract String[] loadRoleInfo (KnownUser user); - /* ------------------------------------------------------------ */ - protected abstract KnownUser loadUserInfo (String username); - /* ------------------------------------------------------------ */ - protected abstract UserIdentity loadUser(String username); - - /* ------------------------------------------------------------ */ - protected abstract void loadUsers() throws IOException; - - - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - public interface UserPrincipal extends Principal,Serializable - { - boolean authenticate(Object credentials); - public boolean isAuthenticated(); - } - - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - public static class RolePrincipal implements Principal,Serializable - { - private static final long serialVersionUID = 2998397924051854402L; - private final String _roleName; - public RolePrincipal(String name) - { - _roleName=name; - } - public String getName() - { - return _roleName; - } - } - - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - public static class Anonymous implements UserPrincipal,Serializable - { - private static final long serialVersionUID = 1097640442553284845L; - - public boolean isAuthenticated() - { - return false; - } - - public String getName() - { - return "Anonymous"; - } - - public boolean authenticate(Object credentials) - { - return false; - } - - } - - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - public static class KnownUser implements UserPrincipal,Serializable - { - private static final long serialVersionUID = -6226920753748399662L; - private final String _name; - private final Credential _credential; - - /* -------------------------------------------------------- */ - public KnownUser(String name,Credential credential) - { - _name=name; - _credential=credential; - } - - /* -------------------------------------------------------- */ - public boolean authenticate(Object credentials) - { - return _credential!=null && _credential.check(credentials); - } - - /* ------------------------------------------------------------ */ - public String getName() - { - return _name; - } - - /* -------------------------------------------------------- */ - public boolean isAuthenticated() - { - return true; - } - - /* -------------------------------------------------------- */ - @Override - public String toString() - { - return _name; - } - } -} - 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 0bab9329574..2d7a6368a64 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 @@ -33,8 +33,7 @@ import java.util.Set; import javax.security.auth.Subject; -import org.eclipse.jetty.security.MappedLoginService.KnownUser; -import org.eclipse.jetty.security.MappedLoginService.RolePrincipal; + import org.eclipse.jetty.server.UserIdentity; import org.eclipse.jetty.util.PathWatcher; import org.eclipse.jetty.util.PathWatcher.PathWatchEvent; @@ -64,17 +63,17 @@ public class PropertyUserStore extends AbstractLifeCycle implements PathWatcher. { private static final Logger LOG = Log.getLogger(PropertyUserStore.class); - private Path _configPath; - private Resource _configResource; + protected Path _configPath; + protected Resource _configResource; - private PathWatcher pathWatcher; - private boolean hotReload = false; // default is not to reload + protected PathWatcher pathWatcher; + protected boolean hotReload = false; // default is not to reload - private IdentityService _identityService = new DefaultIdentityService(); - private boolean _firstLoad = true; // true if first load, false from that point on - private final List _knownUsers = new ArrayList(); - private final Map _knownUserIdentities = new HashMap(); - private List _listeners; + protected IdentityService _identityService = new DefaultIdentityService(); + protected boolean _firstLoad = true; // true if first load, false from that point on + protected final List _knownUsers = new ArrayList(); + protected final Map _knownUserIdentities = new HashMap(); + protected List _listeners; /** * Get the config (as a string) @@ -186,27 +185,7 @@ public class PropertyUserStore extends AbstractLifeCycle implements PathWatcher. this.hotReload = enable; } - /* ------------------------------------------------------------ */ - /** - * sets the refresh interval (in seconds) - * @param sec the refresh interval - * @deprecated use {@link #setHotReload(boolean)} instead - */ - @Deprecated - public void setRefreshInterval(int sec) - { - } - - /* ------------------------------------------------------------ */ - /** - * @return refresh interval in seconds for how often the properties file should be checked for changes - * @deprecated use {@link #isHotReload()} instead - */ - @Deprecated - public int getRefreshInterval() - { - return (hotReload)?1:0; - } + @Override public String toString() @@ -221,7 +200,7 @@ public class PropertyUserStore extends AbstractLifeCycle implements PathWatcher. } /* ------------------------------------------------------------ */ - private void loadUsers() throws IOException + protected void loadUsers() throws IOException { if (_configPath == null) return; @@ -259,7 +238,7 @@ public class PropertyUserStore extends AbstractLifeCycle implements PathWatcher. known.add(username); Credential credential = Credential.getCredential(credentials); - Principal userPrincipal = new KnownUser(username,credential); + Principal userPrincipal = new AbstractLoginService.UserPrincipal(username,credential); Subject subject = new Subject(); subject.getPrincipals().add(userPrincipal); subject.getPrivateCredentials().add(credential); @@ -268,7 +247,7 @@ public class PropertyUserStore extends AbstractLifeCycle implements PathWatcher. { for (String role : roleArray) { - subject.getPrincipals().add(new RolePrincipal(role)); + subject.getPrincipals().add(new AbstractLoginService.RolePrincipal(role)); } } diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/AliasedConstraintTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/AliasedConstraintTest.java index 7da1a9b8892..abf0c7ace5a 100644 --- a/jetty-security/src/test/java/org/eclipse/jetty/security/AliasedConstraintTest.java +++ b/jetty-security/src/test/java/org/eclipse/jetty/security/AliasedConstraintTest.java @@ -62,7 +62,8 @@ public class AliasedConstraintTest private static Server server; private static LocalConnector connector; private static ConstraintSecurityHandler security; - + + @BeforeClass public static void startServer() throws Exception { @@ -73,7 +74,8 @@ public class AliasedConstraintTest ContextHandler context = new ContextHandler(); SessionHandler session = new SessionHandler(); - HashLoginService loginService = new HashLoginService(TEST_REALM); + TestLoginService loginService = new TestLoginService(TEST_REALM); + loginService.putUser("user0",new Password("password"),new String[] {}); loginService.putUser("user",new Password("password"),new String[] { "user" }); loginService.putUser("user2",new Password("password"),new String[] { "user" }); diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java index 4a37e6c82cd..288bd7df882 100644 --- a/jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java +++ b/jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java @@ -85,7 +85,8 @@ public class ConstraintTest ContextHandler _context = new ContextHandler(); SessionHandler _session = new SessionHandler(); - HashLoginService _loginService = new HashLoginService(TEST_REALM); + TestLoginService _loginService = new TestLoginService(TEST_REALM); + _loginService.putUser("user0", new Password("password"), new String[]{}); _loginService.putUser("user",new Password("password"), new String[] {"user"}); _loginService.putUser("user2",new Password("password"), new String[] {"user"}); diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/SpecExampleConstraintTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/SpecExampleConstraintTest.java index 007d5ed978c..004eeab7552 100644 --- a/jetty-security/src/test/java/org/eclipse/jetty/security/SpecExampleConstraintTest.java +++ b/jetty-security/src/test/java/org/eclipse/jetty/security/SpecExampleConstraintTest.java @@ -69,8 +69,9 @@ public class SpecExampleConstraintTest ContextHandler _context = new ContextHandler(); _session = new SessionHandler(); - HashLoginService _loginService = new HashLoginService(TEST_REALM); - _loginService.putUser("fred",new Password("password")); + TestLoginService _loginService = new TestLoginService(TEST_REALM); + + _loginService.putUser("fred",new Password("password"), IdentityService.NO_ROLES); _loginService.putUser("harry",new Password("password"), new String[] {"HOMEOWNER"}); _loginService.putUser("chris",new Password("password"), new String[] {"CONTRACTOR"}); _loginService.putUser("steven", new Password("password"), new String[] {"SALESCLERK"}); 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 new file mode 100644 index 00000000000..222fe136e21 --- /dev/null +++ b/jetty-security/src/test/java/org/eclipse/jetty/security/TestLoginService.java @@ -0,0 +1,69 @@ +// +// ======================================================================== +// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + + +package org.eclipse.jetty.security; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jetty.util.security.Credential; + +/** + * TestLoginService + * + * + */ +public class TestLoginService extends AbstractLoginService +{ + protected Map _users = new HashMap<>(); + protected Map _roles = new HashMap<>(); + + + + public TestLoginService(String name) + { + setName(name); + } + + public void putUser (String username, Credential credential, String[] roles) + { + UserPrincipal userPrincipal = new UserPrincipal(username,credential); + _users.put(username, userPrincipal); + _roles.put(username, roles); + } + + /** + * @see org.eclipse.jetty.security.AbstractLoginService#loadRoleInfo(org.eclipse.jetty.security.AbstractLoginService.UserPrincipal) + */ + @Override + protected String[] loadRoleInfo(UserPrincipal user) + { + return _roles.get(user.getName()); + } + + /** + * @see org.eclipse.jetty.security.AbstractLoginService#loadUserInfo(java.lang.String) + */ + @Override + protected UserPrincipal loadUserInfo(String username) + { + return _users.get(username); + } + +} diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/security/Credential.java b/jetty-util/src/main/java/org/eclipse/jetty/util/security/Credential.java index c763f941569..9c50e1abf32 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/security/Credential.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/security/Credential.java @@ -104,7 +104,20 @@ public abstract class Credential implements Serializable String passwd = credentials.toString(); return _cooked.equals(UnixCrypt.crypt(passwd, _cooked)); } - + + + @Override + public boolean equals (Object credential) + { + if (!(credential instanceof Crypt)) + return false; + + Crypt c = (Crypt)credential; + + return _cooked.equals(c._cooked); + } + + public static String crypt(String user, String pw) { return "CRYPT:" + UnixCrypt.crypt(pw, user); @@ -167,12 +180,7 @@ public abstract class Credential implements Serializable } else if (credentials instanceof MD5) { - MD5 md5 = (MD5) credentials; - if (_digest.length != md5._digest.length) return false; - boolean digestMismatch = false; - for (int i = 0; i < _digest.length; i++) - digestMismatch |= (_digest[i] != md5._digest[i]); - return !digestMismatch; + return equals((MD5)credentials); } else if (credentials instanceof Credential) { @@ -192,6 +200,24 @@ public abstract class Credential implements Serializable return false; } } + + + + @Override + public boolean equals(Object obj) + { + if (obj instanceof MD5) + { + MD5 md5 = (MD5) obj; + if (_digest.length != md5._digest.length) return false; + boolean digestMismatch = false; + for (int i = 0; i < _digest.length; i++) + digestMismatch |= (_digest[i] != md5._digest[i]); + return !digestMismatch; + } + + return false; + } /* ------------------------------------------------------------ */ public static String digest(String password) diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/security/CredentialTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/security/CredentialTest.java new file mode 100644 index 00000000000..a9b25fa10be --- /dev/null +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/security/CredentialTest.java @@ -0,0 +1,79 @@ +// +// ======================================================================== +// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + + +package org.eclipse.jetty.util.security; + + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.eclipse.jetty.util.security.Credential.Crypt; +import org.eclipse.jetty.util.security.Credential.MD5; +import org.junit.Test; + + +/** + * CredentialTest + * + * + */ +public class CredentialTest +{ + + @Test + public void testCrypt() throws Exception + { + Crypt c1 = (Crypt)Credential.getCredential(Crypt.crypt("fred", "abc123")); + Crypt c2 = (Crypt)Credential.getCredential(Crypt.crypt("fred", "abc123")); + + Crypt c3 = (Crypt)Credential.getCredential(Crypt.crypt("fred", "xyz123")); + + Credential c4 = Credential.getCredential(Crypt.crypt("fred", "xyz123")); + + assertTrue(c1.equals(c2)); + assertTrue(c2.equals(c1)); + assertFalse(c1.equals(c3)); + assertFalse(c3.equals(c1)); + assertFalse(c3.equals(c2)); + assertTrue(c4.equals(c3)); + assertFalse(c4.equals(c1)); + + } + + @Test + public void testMD5() throws Exception + { + MD5 m1 = (MD5)Credential.getCredential(MD5.digest("123foo")); + MD5 m2 = (MD5)Credential.getCredential(MD5.digest("123foo")); + MD5 m3 = (MD5)Credential.getCredential(MD5.digest("123boo")); + + assertTrue(m1.equals(m2)); + assertTrue(m2.equals(m1)); + assertFalse(m3.equals(m1)); + } + + @Test + public void testPassword() throws Exception + { + Password p1 = new Password(Password.obfuscate("abc123")); + Credential p2 = Credential.getCredential(Password.obfuscate("abc123")); + + assertTrue (p1.equals(p2)); + } +} 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 11176726e14..33fc4f7e501 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 @@ -25,6 +25,9 @@ import java.net.URI; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServlet; @@ -39,6 +42,7 @@ import org.eclipse.jetty.client.util.BytesContentProvider; import org.eclipse.jetty.client.util.DigestAuthentication; import org.eclipse.jetty.client.util.StringContentProvider; 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.HashLoginService; @@ -55,6 +59,7 @@ import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.security.Constraint; +import org.eclipse.jetty.util.security.Credential; import org.eclipse.jetty.util.security.Password; import org.junit.AfterClass; import org.junit.Assert; @@ -79,6 +84,44 @@ public class DigestPostTest public volatile static String _received = null; private static Server _server; + public static class TestLoginService extends AbstractLoginService + { + protected Map users = new HashMap<>(); + protected Map roles = new HashMap<>(); + + + public TestLoginService(String name) + { + setName(name); + } + + public void putUser (String username, Credential credential, String[] rolenames) + { + UserPrincipal userPrincipal = new UserPrincipal(username,credential); + users.put(username, userPrincipal); + roles.put(username, rolenames); + } + + /** + * @see org.eclipse.jetty.security.AbstractLoginService#loadRoleInfo(org.eclipse.jetty.security.AbstractLoginService.UserPrincipal) + */ + @Override + protected String[] loadRoleInfo(UserPrincipal user) + { + return roles.get(user.getName()); + } + + /** + * @see org.eclipse.jetty.security.AbstractLoginService#loadUserInfo(java.lang.String) + */ + @Override + protected UserPrincipal loadUserInfo(String username) + { + return users.get(username); + } + } + + @BeforeClass public static void setUpServer() { @@ -91,7 +134,7 @@ public class DigestPostTest context.setContextPath("/test"); context.addServlet(PostServlet.class,"/"); - HashLoginService realm = new HashLoginService("test"); + TestLoginService realm = new TestLoginService("test"); realm.putUser("testuser",new Password("password"),new String[]{"test"}); _server.addBean(realm); diff --git a/tests/test-loginservice/src/test/java/org/eclipse/jetty/DataSourceLoginServiceTest.java b/tests/test-loginservice/src/test/java/org/eclipse/jetty/DataSourceLoginServiceTest.java index 51c04c509f5..968858fdc8f 100644 --- a/tests/test-loginservice/src/test/java/org/eclipse/jetty/DataSourceLoginServiceTest.java +++ b/tests/test-loginservice/src/test/java/org/eclipse/jetty/DataSourceLoginServiceTest.java @@ -62,7 +62,6 @@ public class DataSourceLoginServiceTest private static HttpClient _client; private static String __realm = "DSRealm"; private static URI _baseUri; - private static final int __cacheInterval = 200; private static DatabaseLoginServiceTestServer _testServer; @@ -124,7 +123,6 @@ public class DataSourceLoginServiceTest loginService.setUserRoleTableUserKey("user_id"); loginService.setJndiName("dstest"); loginService.setName(__realm); - loginService.setCacheMs(__cacheInterval); if (_testServer != null) loginService.setServer(_testServer.getServer()); @@ -154,7 +152,7 @@ public class DataSourceLoginServiceTest String newpwd = String.valueOf(System.currentTimeMillis()); changePassword("jetty", newpwd); - TimeUnit.MILLISECONDS.sleep(2*__cacheInterval); //pause to ensure cache invalidates + startClient("jetty", newpwd); diff --git a/tests/test-webapps/test-jetty-webapp/src/main/assembly/embedded-jetty-web-for-webbundle.xml b/tests/test-webapps/test-jetty-webapp/src/main/assembly/embedded-jetty-web-for-webbundle.xml index 9b4e89280b2..8726d91a681 100644 --- a/tests/test-webapps/test-jetty-webapp/src/main/assembly/embedded-jetty-web-for-webbundle.xml +++ b/tests/test-webapps/test-jetty-webapp/src/main/assembly/embedded-jetty-web-for-webbundle.xml @@ -54,9 +54,8 @@ detected. Test Realm realm.properties - diff --git a/tests/test-webapps/test-jetty-webapp/src/main/config/demo-base/etc/test-realm.xml b/tests/test-webapps/test-jetty-webapp/src/main/config/demo-base/etc/test-realm.xml index f1b342bf3e4..72c6de06d68 100644 --- a/tests/test-webapps/test-jetty-webapp/src/main/config/demo-base/etc/test-realm.xml +++ b/tests/test-webapps/test-jetty-webapp/src/main/config/demo-base/etc/test-realm.xml @@ -13,7 +13,7 @@ Test Realm - 0 + false diff --git a/tests/test-webapps/test-jetty-webapp/src/main/config/demo-base/webapps/test.xml b/tests/test-webapps/test-jetty-webapp/src/main/config/demo-base/webapps/test.xml index cae730e89d2..d5a5f4bf4c2 100644 --- a/tests/test-webapps/test-jetty-webapp/src/main/config/demo-base/webapps/test.xml +++ b/tests/test-webapps/test-jetty-webapp/src/main/config/demo-base/webapps/test.xml @@ -81,9 +81,8 @@ detected. Test Realm /etc/realm.properties -