483059 Remove cache of authenticated users
This commit is contained in:
parent
18a3af1951
commit
81b2a6a4de
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<String, UserPrincipal> _users = new HashMap<>();
|
||||
protected Map<String, String[]> _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);
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
<New class="org.eclipse.jetty.security.HashLoginService">
|
||||
<Set name="name">Test Realm</Set>
|
||||
<Set name="config"><Property name="jetty.home" default="src/test/config"/>realm.properties</Set>
|
||||
<Set name="refreshInterval">0</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
|
|
@ -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<String> roles = new ArrayList<String>();
|
||||
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
|
||||
{
|
||||
|
|
|
@ -240,7 +240,6 @@
|
|||
<New class="org.eclipse.jetty.security.jaspi.modules.HashLoginService">
|
||||
<Set name="name">Test Realm</Set>
|
||||
<Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</Set>
|
||||
<Set name="refreshInterval">0</Set>
|
||||
</New>
|
||||
</Item>
|
||||
</Array>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
|||
* <p>
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<String> roles = new ArrayList<String>();
|
||||
|
||||
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
|
||||
*/
|
||||
|
|
|
@ -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<String, UserIdentity> _users=new ConcurrentHashMap<String, UserIdentity>();
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
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<String, UserIdentity> 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<String, UserIdentity> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<String> _knownUsers = new ArrayList<String>();
|
||||
private final Map<String, UserIdentity> _knownUserIdentities = new HashMap<String, UserIdentity>();
|
||||
private List<UserListener> _listeners;
|
||||
protected IdentityService _identityService = new DefaultIdentityService();
|
||||
protected boolean _firstLoad = true; // true if first load, false from that point on
|
||||
protected final List<String> _knownUsers = new ArrayList<String>();
|
||||
protected final Map<String, UserIdentity> _knownUserIdentities = new HashMap<String, UserIdentity>();
|
||||
protected List<UserListener> _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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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" });
|
||||
|
|
|
@ -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"});
|
||||
|
|
|
@ -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"});
|
||||
|
|
|
@ -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<String, UserPrincipal> _users = new HashMap<>();
|
||||
protected Map<String, String[]> _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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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<String, UserPrincipal> users = new HashMap<>();
|
||||
protected Map<String, String[]> 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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -54,9 +54,8 @@ detected.
|
|||
<Set name="name">Test Realm</Set>
|
||||
<Set name="config"><Property name="this.web-inf.url"/>realm.properties</Set>
|
||||
<!-- To enable reload of realm when properties change, uncomment the following lines -->
|
||||
<!-- changing refreshInterval (in seconds) as desired -->
|
||||
<!--
|
||||
<Set name="refreshInterval">5</Set>
|
||||
<Set name="hotReload">false</Set>
|
||||
<Call name="start"></Call>
|
||||
-->
|
||||
</New>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<New class="org.eclipse.jetty.security.HashLoginService">
|
||||
<Set name="name">Test Realm</Set>
|
||||
<Set name="config"><Property name="jetty.demo.realm" default="etc/realm.properties"/></Set>
|
||||
<Set name="refreshInterval">0</Set>
|
||||
<Set name="hotReload">false</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
|
|
@ -81,9 +81,8 @@ detected.
|
|||
<Set name="name">Test Realm</Set>
|
||||
<Set name="config"><SystemProperty name="jetty.base" default="."/>/etc/realm.properties</Set>
|
||||
<!-- To enable reload of realm when properties change, uncomment the following lines -->
|
||||
<!-- changing refreshInterval (in seconds) as desired -->
|
||||
<!--
|
||||
<Set name="refreshInterval">5</Set>
|
||||
<Set name="hotReload">true</Set>
|
||||
<Call name="start"></Call>
|
||||
-->
|
||||
</New>
|
||||
|
|
Loading…
Reference in New Issue