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 604dbacef4f..43b58603ea2 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
@@ -18,12 +18,19 @@
package org.eclipse.jetty.security;
+import org.eclipse.jetty.util.PathWatcher;
+import org.eclipse.jetty.util.PathWatcher.PathWatchEvent;
+import org.eclipse.jetty.util.StringUtil;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.resource.PathResource;
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.util.security.Credential;
+
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
-import java.security.Principal;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -31,20 +38,6 @@ import java.util.Map;
import java.util.Properties;
import java.util.Set;
-import javax.security.auth.Subject;
-
-
-import org.eclipse.jetty.server.UserIdentity;
-import org.eclipse.jetty.util.PathWatcher;
-import org.eclipse.jetty.util.PathWatcher.PathWatchEvent;
-import org.eclipse.jetty.util.StringUtil;
-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.resource.PathResource;
-import org.eclipse.jetty.util.resource.Resource;
-import org.eclipse.jetty.util.security.Credential;
-
/**
* PropertyUserStore
*
@@ -59,7 +52,7 @@ 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 PropertyUserStore extends AbstractLifeCycle implements PathWatcher.Listener
+public class PropertyUserStore extends UserStore implements PathWatcher.Listener
{
private static final Logger LOG = Log.getLogger(PropertyUserStore.class);
@@ -69,10 +62,7 @@ public class PropertyUserStore extends AbstractLifeCycle implements PathWatcher.
protected PathWatcher pathWatcher;
protected boolean hotReload = false; // default is not to reload
- 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;
/**
@@ -145,12 +135,6 @@ public class PropertyUserStore extends AbstractLifeCycle implements PathWatcher.
{
_configPath = configPath;
}
-
- /* ------------------------------------------------------------ */
- public UserIdentity getUserIdentity(String userName)
- {
- return _knownUserIdentities.get(userName);
- }
/* ------------------------------------------------------------ */
/**
@@ -199,8 +183,8 @@ public class PropertyUserStore extends AbstractLifeCycle implements PathWatcher.
StringBuilder s = new StringBuilder();
s.append(this.getClass().getName());
s.append("[");
- s.append("users.count=").append(this._knownUsers.size());
- s.append("identityService=").append(this._identityService);
+ s.append("users.count=").append(this.getKnownUserIdentities().size());
+ s.append("identityService=").append(this.getIdentityService());
s.append("]");
return s.toString();
}
@@ -220,7 +204,7 @@ public class PropertyUserStore extends AbstractLifeCycle implements PathWatcher.
if (getConfigResource().exists())
properties.load(getConfigResource().getInputStream());
- Set known = new HashSet();
+ Set known = new HashSet<>();
for (Map.Entry entry : properties.entrySet())
{
@@ -243,27 +227,12 @@ public class PropertyUserStore extends AbstractLifeCycle implements PathWatcher.
}
known.add(username);
Credential credential = Credential.getCredential(credentials);
-
- Principal userPrincipal = new AbstractLoginService.UserPrincipal(username,credential);
- Subject subject = new Subject();
- subject.getPrincipals().add(userPrincipal);
- subject.getPrivateCredentials().add(credential);
-
- if (roles != null)
- {
- for (String role : roleArray)
- {
- subject.getPrincipals().add(new AbstractLoginService.RolePrincipal(role));
- }
- }
-
- subject.setReadOnly();
-
- _knownUserIdentities.put(username,_identityService.newUserIdentity(subject,userPrincipal,roleArray));
+ addUser( username, credential, roleArray );
notifyUpdate(username,credential,roleArray);
}
}
+ final List _knownUsers = new ArrayList();
synchronized (_knownUsers)
{
/*
@@ -277,7 +246,7 @@ public class PropertyUserStore extends AbstractLifeCycle implements PathWatcher.
String user = users.next();
if (!known.contains(user))
{
- _knownUserIdentities.remove(user);
+ removeUser( user );
notifyRemove(user);
}
}
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/UserStore.java b/jetty-security/src/main/java/org/eclipse/jetty/security/UserStore.java
new file mode 100644
index 00000000000..d23a17e9692
--- /dev/null
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/UserStore.java
@@ -0,0 +1,76 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2017 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 org.eclipse.jetty.server.UserIdentity;
+import org.eclipse.jetty.util.component.AbstractLifeCycle;
+import org.eclipse.jetty.util.security.Credential;
+
+import javax.security.auth.Subject;
+import java.security.Principal;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Base class to store User
+ */
+public class UserStore extends AbstractLifeCycle
+{
+ private IdentityService _identityService = new DefaultIdentityService();
+ private final Map _knownUserIdentities = new ConcurrentHashMap<>();
+
+ protected void addUser( String username, Credential credential, String[] roles)
+ {
+ Principal userPrincipal = new AbstractLoginService.UserPrincipal( username, credential);
+ Subject subject = new Subject();
+ subject.getPrincipals().add(userPrincipal);
+ subject.getPrivateCredentials().add(credential);
+
+ if (roles != null)
+ {
+ for (String role : roles)
+ {
+ subject.getPrincipals().add(new AbstractLoginService.RolePrincipal(role));
+ }
+ }
+
+ subject.setReadOnly();
+ _knownUserIdentities.put(username,_identityService.newUserIdentity(subject,userPrincipal,roles));
+ }
+
+ protected void removeUser(String username)
+ {
+ _knownUserIdentities.remove(username);
+ }
+
+ public UserIdentity getUserIdentity(String userName)
+ {
+ return _knownUserIdentities.get(userName);
+ }
+
+ public IdentityService getIdentityService()
+ {
+ return _identityService;
+ }
+
+ protected Map getKnownUserIdentities()
+ {
+ return _knownUserIdentities;
+ }
+}
diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/TestLoginService.java b/jetty-security/src/test/java/org/eclipse/jetty/security/TestLoginService.java
index e8adc097cf8..a977e9bdd31 100644
--- a/jetty-security/src/test/java/org/eclipse/jetty/security/TestLoginService.java
+++ b/jetty-security/src/test/java/org/eclipse/jetty/security/TestLoginService.java
@@ -19,9 +19,14 @@
package org.eclipse.jetty.security;
+import java.security.Principal;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
+import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.security.Credential;
/**
@@ -31,9 +36,8 @@ import org.eclipse.jetty.util.security.Credential;
*/
public class TestLoginService extends AbstractLoginService
{
- protected Map _users = new HashMap<>();
- protected Map _roles = new HashMap<>();
-
+
+ UserStore userStore = new UserStore();
public TestLoginService(String name)
@@ -43,9 +47,7 @@ public class TestLoginService extends AbstractLoginService
public void putUser (String username, Credential credential, String[] roles)
{
- UserPrincipal userPrincipal = new UserPrincipal(username,credential);
- _users.put(username, userPrincipal);
- _roles.put(username, roles);
+ userStore.addUser( username, credential, roles );
}
/**
@@ -54,7 +56,16 @@ public class TestLoginService extends AbstractLoginService
@Override
protected String[] loadRoleInfo(UserPrincipal user)
{
- return _roles.get(user.getName());
+ UserIdentity userIdentity = userStore.getUserIdentity( user.getName() );
+ Set roles = userIdentity.getSubject().getPrincipals( RolePrincipal.class);
+ if (roles == null)
+ return null;
+
+ List list = new ArrayList<>();
+ for (RolePrincipal r:roles)
+ list.add(r.getName());
+
+ return list.toArray(new String[roles.size()]);
}
/**
@@ -63,7 +74,8 @@ public class TestLoginService extends AbstractLoginService
@Override
protected UserPrincipal loadUserInfo(String username)
{
- return _users.get(username);
+ UserIdentity userIdentity = userStore.getUserIdentity( username );
+ return userIdentity == null ? null : (UserPrincipal) userIdentity.getUserPrincipal();
}
}
diff --git a/pom.xml b/pom.xml
index baf709ed44f..f593767451d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -581,7 +581,7 @@
org.apache.maven.plugins
maven-surefire-plugin
- 2.19.1
+ 2.20
@{argLine} -Dfile.encoding=UTF-8 -Duser.language=en -Duser.region=US -showversion -Xmx1g -Xms1g -XX:+PrintGCDetails
false