org.eclipse.jetty.security.ConstraintSecurityHandler Maven / Gradle / Ivy
//
// ========================================================================
// Copyright (c) 1995-2013 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.util.Arrays;
import java.util.Collection;
import java.util.Collections;
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.HttpSchemes;
import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.server.AbstractHttpConnection;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.StringMap;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.security.Constraint;
/* ------------------------------------------------------------ */
/**
* Handler to enforce SecurityConstraints. This implementation is servlet spec
* 2.4 compliant and precomputes the constraint combinations for runtime
* efficiency.
*
*/
public class ConstraintSecurityHandler extends SecurityHandler implements ConstraintAware
{
private final List _constraintMappings= new CopyOnWriteArrayList();
private final Set _roles = new CopyOnWriteArraySet();
private final PathMap _constraintMap = new PathMap();
private boolean _strict = true;
/* ------------------------------------------------------------ */
/** Get the strict mode.
* @return true if the security handler is running in strict mode.
*/
public boolean isStrict()
{
return _strict;
}
/* ------------------------------------------------------------ */
/** Set the strict mode of the security handler.
*
* When in strict mode (the default), the full servlet specification
* will be implemented.
* If not in strict mode, some additional flexibility in configuration
* is allowed:
* - All users do not need to have a role defined in the deployment descriptor
*
- The * role in a constraint applies to ANY role rather than all roles defined in
* the deployment descriptor.
*
*
* @param strict the strict to set
* @see #setRoles(Set)
* @see #setConstraintMappings(List, Set)
*/
public void setStrict(boolean strict)
{
_strict = strict;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the constraintMappings.
*/
public List getConstraintMappings()
{
return _constraintMappings;
}
/* ------------------------------------------------------------ */
public Set getRoles()
{
return _roles;
}
/* ------------------------------------------------------------ */
/**
* Process the constraints following the combining rules in Servlet 3.0 EA
* spec section 13.7.1 Note that much of the logic is in the RoleInfo class.
*
* @param constraintMappings
* The constraintMappings to set, from which the set of known roles
* is determined.
*/
public void setConstraintMappings(List constraintMappings)
{
setConstraintMappings(constraintMappings,null);
}
/**
* Process the constraints following the combining rules in Servlet 3.0 EA
* spec section 13.7.1 Note that much of the logic is in the RoleInfo class.
*
* @param constraintMappings
* The constraintMappings to set as array, from which the set of known roles
* is determined. Needed to retain API compatibility for 7.x
*/
public void setConstraintMappings( ConstraintMapping[] constraintMappings )
{
setConstraintMappings( Arrays.asList(constraintMappings), null);
}
/* ------------------------------------------------------------ */
/**
* Process the constraints following the combining rules in Servlet 3.0 EA
* spec section 13.7.1 Note that much of the logic is in the RoleInfo class.
*
* @param constraintMappings
* The constraintMappings to set.
* @param roles The known roles (or null to determine them from the mappings)
*/
public void setConstraintMappings(List constraintMappings, Set roles)
{
if (isStarted())
throw new IllegalStateException("Started");
_constraintMappings.clear();
_constraintMappings.addAll(constraintMappings);
if (roles==null)
{
roles = new HashSet();
for (ConstraintMapping cm : constraintMappings)
{
String[] cmr = cm.getConstraint().getRoles();
if (cmr!=null)
{
for (String r : cmr)
if (!"*".equals(r))
roles.add(r);
}
}
}
setRoles(roles);
}
/* ------------------------------------------------------------ */
/**
* Set the known roles.
* This may be overridden by a subsequent call to {@link #setConstraintMappings(ConstraintMapping[])} or
* {@link #setConstraintMappings(List, Set)}.
* @see #setStrict(boolean)
* @param roles The known roles (or null to determine them from the mappings)
*/
public void setRoles(Set roles)
{
if (isStarted())
throw new IllegalStateException("Started");
_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())
{
processConstraintMapping(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 map : (Collection