317759 Allow roles and constraints to be added after init

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2043 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2010-06-24 00:39:13 +00:00
parent 3fabec8c5a
commit 517130e909
16 changed files with 213 additions and 144 deletions

View File

@ -8,6 +8,7 @@ jetty-7.1.5-SNAPSHOT
+ 316973 jetty.sh claims java installation is invalid
+ 316976 removed quotes of JAVA_OPTIONS in jetty.sh
+ 317019 Date HTTP header not sent for HTTP/1.0 requests
+ 317759 Allow roles and constraints to be added after init
+ JETTY-1237 Save local/remote address to be available after close
jetty-7.1.4.v20100610

View File

@ -13,6 +13,7 @@
package org.eclipse.jetty.embedded;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@ -49,7 +50,7 @@ public class SecuredHelloHandler
knownRoles.add("user");
knownRoles.add("admin");
security.setConstraintMappings(new ConstraintMapping[] {mapping}, knownRoles);
security.setConstraintMappings(Collections.singletonList(mapping), knownRoles);
security.setAuthenticator(new BasicAuthenticator());
security.setLoginService(loginService);
security.setStrict(false);

View File

@ -13,6 +13,7 @@
package org.eclipse.jetty.client;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@ -78,7 +79,7 @@ public class SecuredContentExchangeTest
knownRoles.add("user");
knownRoles.add("admin");
security.setConstraintMappings(new ConstraintMapping[] {mapping}, knownRoles);
security.setConstraintMappings(Collections.singletonList(mapping), knownRoles);
security.setAuthenticator(new BasicAuthenticator());
security.setLoginService(loginService);
security.setStrict(false);

View File

@ -13,6 +13,7 @@
package org.eclipse.jetty.client;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@ -144,7 +145,7 @@ public class SecuredErrorStatusTest
knownRoles.add("user");
knownRoles.add("admin");
security.setConstraintMappings(new ConstraintMapping[] {mapping}, knownRoles);
security.setConstraintMappings(Collections.singletonList(mapping), knownRoles);
security.setAuthenticator(new BasicAuthenticator());
security.setLoginService(loginService);
security.setStrict(false);

View File

@ -14,6 +14,7 @@
package org.eclipse.jetty.client;
import java.io.File;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@ -83,7 +84,7 @@ extends ContentExchangeTest
knownRoles.add("user");
knownRoles.add("admin");
security.setConstraintMappings(new ConstraintMapping[] {mapping}, knownRoles);
security.setConstraintMappings(Collections.singletonList(mapping), knownRoles);
security.setAuthenticator(new BasicAuthenticator());
security.setLoginService(loginService);
security.setStrict(false);

View File

@ -13,6 +13,7 @@
package org.eclipse.jetty.client;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@ -144,7 +145,7 @@ public class SslSecuredErrorStatusTest
knownRoles.add("user");
knownRoles.add("admin");
security.setConstraintMappings(new ConstraintMapping[] {mapping}, knownRoles);
security.setConstraintMappings(Collections.singletonList(mapping), knownRoles);
security.setAuthenticator(new BasicAuthenticator());
security.setLoginService(loginService);
security.setStrict(false);

View File

@ -18,6 +18,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CyclicBarrier;
@ -170,7 +171,7 @@ public class SslSecurityListenerTest extends TestCase
sh.setAuthenticator(authenticator);
Set<String> roles = new HashSet<String>(Arrays.asList(new String[]{"user", "admin"}));
sh.setConstraintMappings(new ConstraintMapping[] { cm }, roles);
sh.setConstraintMappings(Collections.singletonList(cm), roles);
_server.setHandler(sh);
Handler testHandler = new AbstractHandler()

View File

@ -13,6 +13,7 @@
package org.eclipse.jetty.security;
import java.util.List;
import java.util.Set;
/**
@ -20,9 +21,29 @@ import java.util.Set;
*/
public interface ConstraintAware
{
ConstraintMapping[] getConstraintMappings();
List<ConstraintMapping> getConstraintMappings();
Set<String> getRoles();
void setConstraintMappings(ConstraintMapping[] constraintMappings, Set<String> roles);
/* ------------------------------------------------------------ */
/** Set Constraint Mappings and roles.
* Can only be called during initialization.
* @param constraintMappings
* @param roles
*/
void setConstraintMappings(List<ConstraintMapping> constraintMappings, Set<String> roles);
/* ------------------------------------------------------------ */
/** Add a Constraint Mapping.
* May be called for running webapplication as an annotated servlet is instantiated.
* @param mapping
*/
void addConstraintMapping(ConstraintMapping mapping);
/* ------------------------------------------------------------ */
/** Add a Role definition.
* May be called on running webapplication as an annotated servlet is instantiated.
* @param role
*/
void addRole(String role);
}

View File

@ -14,9 +14,13 @@
package org.eclipse.jetty.security;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.http.security.Constraint;
@ -36,9 +40,9 @@ import org.eclipse.jetty.util.StringMap;
*/
public class ConstraintSecurityHandler extends SecurityHandler implements ConstraintAware
{
private ConstraintMapping[] _constraintMappings;
private Set<String> _roles;
private PathMap _constraintMap = new PathMap();
private final List<ConstraintMapping> _constraintMappings= new CopyOnWriteArrayList<ConstraintMapping>();
private final Set<String> _roles = new CopyOnWriteArraySet<String>();
private final PathMap _constraintMap = new PathMap();
private boolean _strict = true;
@ -76,7 +80,7 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
/**
* @return Returns the contraintMappings.
*/
public ConstraintMapping[] getConstraintMappings()
public List<ConstraintMapping> getConstraintMappings()
{
return _constraintMappings;
}
@ -96,7 +100,7 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
* The contraintMappings to set, from which the set of known roles
* is determined.
*/
public void setConstraintMappings(ConstraintMapping[] constraintMappings)
public void setConstraintMappings(List<ConstraintMapping> constraintMappings)
{
setConstraintMappings(constraintMappings,null);
}
@ -110,11 +114,12 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
* The contraintMappings to set.
* @param roles The known roles (or null to determine them from the mappings)
*/
public void setConstraintMappings(ConstraintMapping[] constraintMappings, Set<String> roles)
public void setConstraintMappings(List<ConstraintMapping> constraintMappings, Set<String> roles)
{
if (isStarted())
throw new IllegalStateException("Started");
_constraintMappings = constraintMappings;
_constraintMappings.clear();
_constraintMappings.addAll(constraintMappings);
if (roles==null)
{
@ -146,7 +151,48 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
if (isStarted())
throw new IllegalStateException("Started");
this._roles = roles;
_roles.clear();
_roles.addAll(roles);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.security.ConstraintAware#addConstraintMapping(org.eclipse.jetty.security.ConstraintMapping)
*/
public void addConstraintMapping(ConstraintMapping mapping)
{
_constraintMappings.add(mapping);
if (mapping.getConstraint()!=null && mapping.getConstraint().getRoles()!=null)
for (String role : mapping.getConstraint().getRoles())
addRole(role);
if (isStarted())
{
processContraintMapping(mapping);
}
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.security.ConstraintAware#addRole(java.lang.String)
*/
public void addRole(String role)
{
boolean modified = _roles.add(role);
if (isStarted() && modified && _strict)
{
// Add the new role to currently defined any role role infos
for (Map<String,RoleInfo> map : (Collection<Map<String,RoleInfo>>)_constraintMap.values())
{
for (RoleInfo info : map.values())
{
if (info.isAnyRole())
info.addRole(role);
}
}
}
}
/* ------------------------------------------------------------ */
@ -161,92 +207,95 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
{
for (ConstraintMapping mapping : _constraintMappings)
{
Map<String, RoleInfo> mappings = (Map<String, RoleInfo>)_constraintMap.get(mapping.getPathSpec());
if (mappings == null)
{
mappings = new StringMap();
_constraintMap.put(mapping.getPathSpec(),mappings);
}
RoleInfo allMethodsRoleInfo = mappings.get(null);
if (allMethodsRoleInfo != null && allMethodsRoleInfo.isForbidden())
{
continue;
}
String httpMethod = mapping.getMethod();
RoleInfo roleInfo = mappings.get(httpMethod);
if (roleInfo == null)
{
roleInfo = new RoleInfo();
mappings.put(httpMethod,roleInfo);
if (allMethodsRoleInfo != null)
{
roleInfo.combine(allMethodsRoleInfo);
}
}
if (roleInfo.isForbidden())
{
continue;
}
Constraint constraint = mapping.getConstraint();
boolean forbidden = constraint.isForbidden();
roleInfo.setForbidden(forbidden);
if (forbidden)
{
if (httpMethod == null)
{
mappings.clear();
mappings.put(null,roleInfo);
}
}
else
{
UserDataConstraint userDataConstraint = UserDataConstraint.get(constraint.getDataConstraint());
roleInfo.setUserDataConstraint(userDataConstraint);
boolean checked = constraint.getAuthenticate();
roleInfo.setChecked(checked);
if (roleInfo.isChecked())
{
if (constraint.isAnyRole())
{
if (_strict)
{
// * means "all defined roles"
for (String role : _roles)
roleInfo.addRole(role);
}
else
// * means any role
roleInfo.setAnyRole(true);
}
else
{
String[] newRoles = constraint.getRoles();
for (String role : newRoles)
{
if (_strict &&!_roles.contains(role))
throw new IllegalArgumentException("Attempt to use undeclared role: " + role + ", known roles: " + _roles);
roleInfo.addRole(role);
}
}
}
if (httpMethod == null)
{
for (Map.Entry<String, RoleInfo> entry : mappings.entrySet())
{
if (entry.getKey() != null)
{
RoleInfo specific = entry.getValue();
specific.combine(roleInfo);
}
}
}
}
processContraintMapping(mapping);
}
}
super.doStart();
}
protected void processContraintMapping(ConstraintMapping mapping)
{
Map<String, RoleInfo> mappings = (Map<String, RoleInfo>)_constraintMap.get(mapping.getPathSpec());
if (mappings == null)
{
mappings = new StringMap();
_constraintMap.put(mapping.getPathSpec(),mappings);
}
RoleInfo allMethodsRoleInfo = mappings.get(null);
if (allMethodsRoleInfo != null && allMethodsRoleInfo.isForbidden())
return;
String httpMethod = mapping.getMethod();
RoleInfo roleInfo = mappings.get(httpMethod);
if (roleInfo == null)
{
roleInfo = new RoleInfo();
mappings.put(httpMethod,roleInfo);
if (allMethodsRoleInfo != null)
{
roleInfo.combine(allMethodsRoleInfo);
}
}
if (roleInfo.isForbidden())
return;
Constraint constraint = mapping.getConstraint();
boolean forbidden = constraint.isForbidden();
roleInfo.setForbidden(forbidden);
if (forbidden)
{
if (httpMethod == null)
{
mappings.clear();
mappings.put(null,roleInfo);
}
}
else
{
UserDataConstraint userDataConstraint = UserDataConstraint.get(constraint.getDataConstraint());
roleInfo.setUserDataConstraint(userDataConstraint);
boolean checked = constraint.getAuthenticate();
roleInfo.setChecked(checked);
if (roleInfo.isChecked())
{
if (constraint.isAnyRole())
{
if (_strict)
{
// * means "all defined roles"
for (String role : _roles)
roleInfo.addRole(role);
}
else
// * means any role
roleInfo.setAnyRole(true);
}
else
{
String[] newRoles = constraint.getRoles();
for (String role : newRoles)
{
if (_strict &&!_roles.contains(role))
throw new IllegalArgumentException("Attempt to use undeclared role: " + role + ", known roles: " + _roles);
roleInfo.addRole(role);
}
}
}
if (httpMethod == null)
{
for (Map.Entry<String, RoleInfo> entry : mappings.entrySet())
{
if (entry.getKey() != null)
{
RoleInfo specific = entry.getValue();
specific.combine(roleInfo);
}
}
}
}
}
protected Object prepareConstraintInfo(String pathInContext, Request request)
{
Map<String, RoleInfo> mappings = (Map<String, RoleInfo>)_constraintMap.match(pathInContext);
@ -353,8 +402,7 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
if (roleInfo.isAnyRole() && request.getAuthType()!=null)
return true;
String[] roles = roleInfo.getRoles();
for (String role : roles)
for (String role : roleInfo.getRoles())
{
if (userIdentity.isUserInRole(role, null))
return true;

View File

@ -24,7 +24,6 @@ import java.util.List;
import java.util.Properties;
import org.eclipse.jetty.http.security.Credential;
import org.eclipse.jetty.http.security.Password;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.log.Log;

View File

@ -13,9 +13,8 @@
package org.eclipse.jetty.security;
import java.util.Arrays;
import org.eclipse.jetty.util.LazyList;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
/**
*
@ -27,13 +26,12 @@ import org.eclipse.jetty.util.LazyList;
*/
public class RoleInfo
{
private final static String[] NO_ROLES={};
private boolean _isAnyRole;
private boolean _checked;
private boolean _forbidden;
private UserDataConstraint _userDataConstraint;
private String[] _roles = NO_ROLES;
private final Set<String> _roles = new CopyOnWriteArraySet<String>();
public RoleInfo()
{
@ -50,7 +48,7 @@ public class RoleInfo
if (!checked)
{
_forbidden=false;
_roles=NO_ROLES;
_roles.clear();
_isAnyRole=false;
}
}
@ -68,7 +66,7 @@ public class RoleInfo
_checked = true;
_userDataConstraint = null;
_isAnyRole=false;
_roles=NO_ROLES;
_roles.clear();
}
}
@ -83,7 +81,7 @@ public class RoleInfo
if (anyRole)
{
_checked = true;
_roles=NO_ROLES;
_roles.clear();
}
}
@ -105,14 +103,14 @@ public class RoleInfo
}
}
public String[] getRoles()
public Set<String> getRoles()
{
return _roles;
}
public void addRole(String role)
{
_roles=(String[])LazyList.addToArray(_roles,role,String.class);
_roles.add(role);
}
public void combine(RoleInfo other)
@ -126,14 +124,15 @@ public class RoleInfo
else if (!_isAnyRole)
{
for (String r : other._roles)
_roles=(String[])LazyList.addToArray(_roles,r,String.class);
_roles.add(r);
}
setUserDataConstraint(other._userDataConstraint);
}
@Override
public String toString()
{
return "{RoleInfo"+(_forbidden?",F":"")+(_checked?",C":"")+(_isAnyRole?",*":Arrays.asList(_roles).toString())+"}";
return "{RoleInfo"+(_forbidden?",F":"")+(_checked?",C":"")+(_isAnyRole?",*":_roles)+"}";
}
}

View File

@ -13,11 +13,16 @@
package org.eclipse.jetty.security;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -41,9 +46,6 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @version $Revision: 1441 $ $Date: 2010-04-02 12:28:17 +0200 (Fri, 02 Apr 2010) $
*/
@ -128,10 +130,10 @@ public class ConstraintTest
knownRoles.add("user");
knownRoles.add("administrator");
_security.setConstraintMappings(new ConstraintMapping[]
_security.setConstraintMappings(Arrays.asList(new ConstraintMapping[]
{
mapping0, mapping1, mapping2, mapping3, mapping4
}, knownRoles);
}), knownRoles);
}
@After
@ -147,7 +149,7 @@ public class ConstraintTest
@Test
public void testConstraints() throws Exception
{
ConstraintMapping[] mappings =_security.getConstraintMappings();
ConstraintMapping[] mappings =_security.getConstraintMappings().toArray(new ConstraintMapping[0]);
assertTrue (mappings[0].getConstraint().isForbidden());
assertFalse(mappings[1].getConstraint().isForbidden());

View File

@ -158,8 +158,6 @@ public class WebXmlConfiguration implements Configuration
context.setEventListeners(null);
context.setWelcomeFiles(null);
if (_securityHandler instanceof ConstraintAware)
((ConstraintAware) _securityHandler).setConstraintMappings(new ConstraintMapping[]{}, Collections.EMPTY_SET);
if (context.getErrorHandler() instanceof ErrorPageErrorHandler)
((ErrorPageErrorHandler)

View File

@ -47,12 +47,9 @@ import org.eclipse.jetty.xml.XmlParser;
/**
* WebXmlProcessor
*
*
*/
public class WebXmlProcessor
{
@ -76,8 +73,8 @@ public class WebXmlProcessor
protected Object _servletMappings;
protected Object _listeners;
protected Object _welcomeFiles;
protected Set<String> _roles = new HashSet<String>();
protected Object _constraintMappings;
protected Set<String> _newRoles = new HashSet<String>();
protected List<ConstraintMapping> _newConstraintMappings;
protected Map _errorPages;
protected boolean _hasJSP;
protected String _jspServletName;
@ -395,15 +392,10 @@ public class WebXmlProcessor
_servletMappings = LazyList.array2List(_servletHandler.getServletMappings());
_listeners = LazyList.array2List(_context.getEventListeners());
_welcomeFiles = LazyList.array2List(_context.getWelcomeFiles());
if (_securityHandler instanceof ConstraintAware)
{
_constraintMappings = LazyList.array2List(((ConstraintAware) _securityHandler).getConstraintMappings());
if (((ConstraintAware) _securityHandler).getRoles() != null)
{
_roles.addAll(((ConstraintAware) _securityHandler).getRoles());
}
}
_newConstraintMappings=new ArrayList<ConstraintMapping>();
_newRoles=new HashSet<String>();
_errorPages = _context.getErrorHandler() instanceof ErrorPageErrorHandler ? ((ErrorPageErrorHandler)_context.getErrorHandler()).getErrorPages() : null;
Iterator iter = config.iterator();
@ -439,9 +431,10 @@ public class WebXmlProcessor
// TODO jaspi check this
if (_securityHandler instanceof ConstraintAware)
{
((ConstraintAware) _securityHandler).setConstraintMappings((ConstraintMapping[]) LazyList.toArray(_constraintMappings,
ConstraintMapping.class),
_roles);
for (String role : _newRoles)
((ConstraintAware)_securityHandler).addRole(role);
for (ConstraintMapping mapping : _newConstraintMappings)
((ConstraintAware)_securityHandler).addConstraintMapping(mapping);
}
if (_errorPages != null && _context.getErrorHandler() instanceof ErrorPageErrorHandler)
@ -987,7 +980,7 @@ public class WebXmlProcessor
mapping.setMethod(method);
mapping.setPathSpec(url);
mapping.setConstraint(sc);
_constraintMappings = LazyList.add(_constraintMappings, mapping);
_newConstraintMappings.add(mapping);
}
}
else
@ -995,7 +988,7 @@ public class WebXmlProcessor
ConstraintMapping mapping = new ConstraintMapping();
mapping.setPathSpec(url);
mapping.setConstraint(sc);
_constraintMappings = LazyList.add(_constraintMappings, mapping);
_newConstraintMappings.add(mapping);
}
}
}
@ -1047,7 +1040,7 @@ public class WebXmlProcessor
{
XmlParser.Node roleNode = node.get("role-name");
String role = roleNode.toString(false, true);
_roles.add(role);
_newRoles.add(role);
}
/* ------------------------------------------------------------ */

View File

@ -5,6 +5,7 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;
import java.security.MessageDigest;
import java.util.Collections;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@ -82,7 +83,7 @@ public class DigestPostTest
mapping.setConstraint(constraint);
mapping.setPathSpec("/*");
security.setConstraintMappings(new ConstraintMapping[]{mapping});
security.setConstraintMappings(Collections.singletonList(mapping));
HandlerCollection handlers = new HandlerCollection();
handlers.setHandlers(new Handler[]

View File

@ -29,6 +29,7 @@ import java.net.URLDecoder;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.HashSet;
import java.util.Collections;
import java.util.Set;
import javax.servlet.ServletException;
@ -166,7 +167,7 @@ public class JdbcLoginServiceTest
knownRoles.add("user");
knownRoles.add("admin");
security.setConstraintMappings(new ConstraintMapping[] {mapping}, knownRoles);
security.setConstraintMappings(Collections.singletonList(mapping), knownRoles);
security.setAuthenticator(new BasicAuthenticator());
security.setLoginService(loginService);
security.setStrict(false);