390163 Implement ServletRegistration.Dynamic.setServletSecurity

This commit is contained in:
Jan Bartel 2012-09-29 16:15:55 +10:00
parent c7e36470c5
commit ce3ba58887
11 changed files with 377 additions and 158 deletions

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.annotations;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletSecurityElement;
import javax.servlet.annotation.HttpConstraint;
import javax.servlet.annotation.HttpMethodConstraint;
import javax.servlet.annotation.ServletSecurity;
@ -30,12 +31,13 @@ import javax.servlet.annotation.ServletSecurity.TransportGuarantee;
import org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler;
import org.eclipse.jetty.security.ConstraintAware;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.webapp.Origin;
import org.eclipse.jetty.webapp.WebAppContext;
/**
@ -82,7 +84,7 @@ public class ServletSecurityAnnotationHandler extends AbstractIntrospectableAnno
if (servletSecurity == null)
return;
//If there are already constraints defined (ie from web.xml or programmatically(?)) that match any
//If there are already constraints defined (ie from web.xml) that match any
//of the url patterns defined for this servlet, then skip the security annotation.
List<ServletMapping> servletMappings = getServletMappings(clazz.getCanonicalName());
@ -97,19 +99,15 @@ public class ServletSecurityAnnotationHandler extends AbstractIntrospectableAnno
//Make a fresh list
constraintMappings = new ArrayList<ConstraintMapping>();
//Get the values that form the constraints that will apply unless there are HttpMethodConstraints to augment them
HttpConstraint defaults = servletSecurity.value();
//Make a Constraint for the <auth-constraint> and <user-data-constraint> specified by the HttpConstraint
Constraint defaultConstraint = makeConstraint (clazz,
defaults.rolesAllowed(),
defaults.value(),
defaults.transportGuarantee());
constraintMappings.addAll(makeMethodMappings(clazz,
defaultConstraint,
servletMappings,
servletSecurity.httpMethodConstraints()));
ServletSecurityElement securityElement = new ServletSecurityElement(servletSecurity);
for (ServletMapping sm : servletMappings)
{
for (String url : sm.getPathSpecs())
{
_context.getMetaData().setOrigin("constraint.url."+url, Origin.Annotation);
constraintMappings.addAll(ConstraintSecurityHandler.createConstraintsWithMappingsForPath(clazz.getName(), url, securityElement));
}
}
//set up the security constraints produced by the annotation
ConstraintAware securityHandler = (ConstraintAware)_context.getSecurityHandler();
@ -131,111 +129,10 @@ public class ServletSecurityAnnotationHandler extends AbstractIntrospectableAnno
*/
protected Constraint makeConstraint (Class servlet, String[] rolesAllowed, EmptyRoleSemantic permitOrDeny, TransportGuarantee transport)
{
Constraint constraint = new Constraint();
if (rolesAllowed == null || rolesAllowed.length==0)
{
if (permitOrDeny.equals(EmptyRoleSemantic.DENY))
{
//Equivalent to <auth-constraint> with no roles
constraint.setName(servlet.getName()+"-Deny");
constraint.setAuthenticate(true);
}
else
{
//Equivalent to no <auth-constraint>
constraint.setAuthenticate(false);
constraint.setName(servlet.getName()+"-Permit");
}
}
else
{
//Equivalent to <auth-constraint> with list of <security-role-name>s
constraint.setAuthenticate(true);
constraint.setRoles(rolesAllowed);
constraint.setName(servlet.getName()+"-RolesAllowed");
}
//Equivalent to //<user-data-constraint><transport-guarantee>CONFIDENTIAL</transport-guarantee></user-data-constraint>
constraint.setDataConstraint((transport.equals(TransportGuarantee.CONFIDENTIAL)?Constraint.DC_CONFIDENTIAL:Constraint.DC_NONE));
return constraint;
return ConstraintSecurityHandler.createConstraint(servlet.getName(), rolesAllowed, permitOrDeny, transport);
}
/**
* Make a ConstraintMapping which captures the <http-method> or <http-method-omission> elements for a particular url pattern,
* and relates it to a Constraint object (<auth-constraint> and <user-data-constraint>).
* @param constraint
* @param url
* @param method
* @param omissions
* @return
*/
protected ConstraintMapping makeConstraintMapping (Constraint constraint, String url, String method, String[] omissions)
{
ConstraintMapping mapping = new ConstraintMapping();
mapping.setConstraint(constraint);
mapping.setPathSpec(url);
if (method != null)
mapping.setMethod(method);
if (omissions != null)
mapping.setMethodOmissions(omissions);
return mapping;
}
/**
* Make the Jetty Constraints and ConstraintMapping objects that correspond to the HttpMethodConstraint
* annotations for each url pattern for the servlet.
* @param servlet
* @param defaultConstraint
* @param servletMappings
* @param annotations
* @return
*/
protected List<ConstraintMapping> makeMethodMappings (Class servlet, Constraint defaultConstraint, List<ServletMapping> servletMappings, HttpMethodConstraint[] annotations)
{
List<ConstraintMapping> mappings = new ArrayList<ConstraintMapping>();
//for each url-pattern existing for the servlet make a ConstraintMapping for the HttpConstraint, and ConstraintMappings for
//each HttpMethodConstraint
for (ServletMapping sm : servletMappings)
{
for (String url : sm.getPathSpecs())
{
//Make a ConstraintMapping that matches the defaultConstraint
ConstraintMapping defaultMapping = makeConstraintMapping(defaultConstraint, url, null, null);
//If there are HttpMethodConstraint annotations, make a Constraint and a ConstraintMapping for it
if (annotations != null && annotations.length>0)
{
List<String> omissions = new ArrayList<String>();
//for each HttpMethodConstraint annotation, make a new Constraint and ConstraintMappings for this url
for (int i=0; i < annotations.length;i++)
{
//Make a Constraint that captures the <auth-constraint> and <user-data-constraint> elements
Constraint methodConstraint = makeConstraint(servlet,
annotations[i].rolesAllowed(),
annotations[i].emptyRoleSemantic(),
annotations[i].transportGuarantee());
//Make ConstraintMapping that captures the <http-method> elements
ConstraintMapping methodConstraintMapping = makeConstraintMapping (methodConstraint,
url,annotations[i].value(),
null);
mappings.add(methodConstraintMapping);
omissions.add(annotations[i].value());
}
defaultMapping.setMethodOmissions(omissions.toArray(new String[0]));
}
//add the constraint mapping containing the http-method-omissions, if there are any
mappings.add(defaultMapping);
}
}
return mappings;
}
/**
* Get the ServletMappings for the servlet's class.
@ -284,6 +181,7 @@ public class ServletSecurityAnnotationHandler extends AbstractIntrospectableAnno
{
for (int j=0; j < pathSpecs.length; j++)
{
//TODO decide if we need to check the origin
if (pathSpecs[j].equals(constraintMappings.get(i).getPathSpec()))
{
exists = true;

View File

@ -24,7 +24,6 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@ -51,7 +50,7 @@ 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
* 3.0 compliant and precomputes the constraint combinations for runtime
* efficiency.
*
*/
@ -191,9 +190,11 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
/* ------------------------------------------------------------ */
/**
/** Take out of the constraint mappings those that match the
* given path.
*
* @param pathSpec
* @param constraintMappings
* @param constraintMappings a new list minus the matching constraints
* @return
*/
public static List<ConstraintMapping> removeConstraintMappingsForPath(String pathSpec, List<ConstraintMapping> constraintMappings)
@ -351,8 +352,6 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
*/
public void setConstraintMappings(List<ConstraintMapping> constraintMappings, Set<String> roles)
{
if (isStarted())
throw new IllegalStateException("Started");
_constraintMappings.clear();
_constraintMappings.addAll(constraintMappings);
@ -371,6 +370,14 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
}
}
setRoles(roles);
if (isStarted())
{
for (ConstraintMapping mapping : _constraintMappings)
{
processConstraintMapping(mapping);
}
}
}
/* ------------------------------------------------------------ */
@ -383,9 +390,6 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
*/
public void setRoles(Set<String> roles)
{
if (isStarted())
throw new IllegalStateException("Started");
_roles.clear();
_roles.addAll(roles);
}

View File

@ -48,6 +48,7 @@ import javax.servlet.descriptor.JspPropertyGroupDescriptor;
import javax.servlet.descriptor.TaglibDescriptor;
import org.eclipse.jetty.security.ConstraintAware;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.server.Dispatcher;
@ -59,6 +60,7 @@ import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.security.Constraint;
/* ------------------------------------------------------------ */
@ -377,10 +379,21 @@ public class ServletContextHandler extends ContextHandler
* @param registration ServletRegistration.Dynamic instance that setServletSecurity was called on
* @param servletSecurityElement new security info
* @return the set of exact URL mappings currently associated with the registration that are also present in the web.xml
* security constratins and thus will be unaffected by this call.
* security constraints and thus will be unaffected by this call.
*/
public Set<String> setServletSecurity(ServletRegistration.Dynamic registration, ServletSecurityElement servletSecurityElement)
{
//Default implementation is to just accept them all. If using a webapp, then this behaviour is overridden in WebAppContext.setServletSecurity
Collection<String> pathSpecs = registration.getMappings();
if (pathSpecs != null)
{
for (String pathSpec:pathSpecs)
{
List<ConstraintMapping> mappings = ConstraintSecurityHandler.createConstraintsWithMappingsForPath(registration.getName(), pathSpec, servletSecurityElement);
for (ConstraintMapping m:mappings)
((ConstraintAware)getSecurityHandler()).addConstraintMapping(m);
}
}
return Collections.emptySet();
}

View File

@ -538,6 +538,15 @@ public class MetaData
OriginInfo x = new OriginInfo (name, Origin.Annotation);
_origins.put(name, x);
}
public void setOrigin(String name, Origin origin)
{
if (name == null)
return;
OriginInfo x = new OriginInfo (name, origin);
_origins.put(name, x);
}
public boolean isMetaDataComplete()
{

View File

@ -18,4 +18,4 @@
package org.eclipse.jetty.webapp;
public enum Origin {NotSet, WebXml, WebDefaults, WebOverride, WebFragment, Annotation}
public enum Origin {NotSet, WebXml, WebDefaults, WebOverride, WebFragment, Annotation, API}

View File

@ -25,18 +25,29 @@ import java.net.URL;
import java.security.PermissionCollection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EventListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.HttpMethodConstraintElement;
import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration.Dynamic;
import javax.servlet.ServletSecurityElement;
import javax.servlet.annotation.ServletSecurity.EmptyRoleSemantic;
import javax.servlet.annotation.ServletSecurity.TransportGuarantee;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionListener;
import org.eclipse.jetty.security.ConstraintAware;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HandlerContainer;
@ -56,6 +67,7 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceCollection;
import org.eclipse.jetty.util.security.Constraint;
/* ------------------------------------------------------------ */
/** Web Application Context Handler.
@ -1237,6 +1249,79 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
super.startContext();
}
/* ------------------------------------------------------------ */
@Override
public Set<String> setServletSecurity(Dynamic registration, ServletSecurityElement servletSecurityElement)
{
Set<String> unchangedURLMappings = new HashSet<String>();
//From javadoc for ServletSecurityElement:
/*
If a URL pattern of this ServletRegistration is an exact target of a security-constraint that
was established via the portable deployment descriptor, then this method does not change the
security-constraint for that pattern, and the pattern will be included in the return value.
If a URL pattern of this ServletRegistration is an exact target of a security constraint
that was established via the ServletSecurity annotation or a previous call to this method,
then this method replaces the security constraint for that pattern.
If a URL pattern of this ServletRegistration is neither the exact target of a security constraint
that was established via the ServletSecurity annotation or a previous call to this method,
nor the exact target of a security-constraint in the portable deployment descriptor, then
this method establishes the security constraint for that pattern from the argument ServletSecurityElement.
*/
Collection<String> pathMappings = registration.getMappings();
if (pathMappings != null)
{
Constraint constraint = ConstraintSecurityHandler.createConstraint(registration.getName(), servletSecurityElement);
for (String pathSpec:pathMappings)
{
Origin origin = getMetaData().getOrigin("constraint.url."+pathSpec);
switch (origin)
{
case NotSet:
{
//No mapping for this url already established
List<ConstraintMapping> mappings = ConstraintSecurityHandler.createConstraintsWithMappingsForPath(registration.getName(), pathSpec, servletSecurityElement);
for (ConstraintMapping m:mappings)
((ConstraintAware)getSecurityHandler()).addConstraintMapping(m);
getMetaData().setOrigin("constraint.url."+pathSpec, Origin.API);
break;
}
case WebXml:
case WebDefaults:
case WebOverride:
case WebFragment:
{
//a mapping for this url was created in a descriptor, which overrides everything
unchangedURLMappings.add(pathSpec);
break;
}
case Annotation:
case API:
{
//mapping established via an annotation or by previous call to this method,
//replace the security constraint for this pattern
List<ConstraintMapping> constraintMappings = ConstraintSecurityHandler.removeConstraintMappingsForPath(pathSpec, ((ConstraintAware)getSecurityHandler()).getConstraintMappings());
List<ConstraintMapping> freshMappings = ConstraintSecurityHandler.createConstraintsWithMappingsForPath(registration.getName(), pathSpec, servletSecurityElement);
constraintMappings.addAll(freshMappings);
((ConstraintSecurityHandler)getSecurityHandler()).setConstraintMappings(constraintMappings);
break;
}
}
}
}
return unchangedURLMappings;
}
/* ------------------------------------------------------------ */
public class Context extends ServletContextHandler.Context
@ -1287,6 +1372,8 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
}
}
}
/* ------------------------------------------------------------ */

View File

@ -15,15 +15,6 @@
<param-value>a context value</param-value>
</context-param>
<!-- Add or override filter init parameter -->
<filter>
<filter-name>TestFilter</filter-name>
<filter-class>com.acme.TestFilter</filter-class>
<init-param>
<param-name>remote</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<!-- Add or override servlet init parameter -->
<servlet>

View File

@ -0,0 +1,194 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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 com.acme;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.util.StringUtil;
/* ------------------------------------------------------------ */
/** Rego Servlet - tests being accessed from servlet 3.0 programmatic
* configuration.
*
*/
public class RegTest extends HttpServlet
{
/* ------------------------------------------------------------ */
@Override
public void init(ServletConfig config) throws ServletException
{
super.init(config);
}
/* ------------------------------------------------------------ */
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doGet(request, response);
}
/* ------------------------------------------------------------ */
@Override
public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
{
request.setCharacterEncoding("UTF-8");
PrintWriter pout=null;
try
{
pout =response.getWriter();
}
catch(IllegalStateException e)
{
pout=new PrintWriter(new OutputStreamWriter(response.getOutputStream(),"UTF-8"));
}
try
{
pout.write("<html>\n<body>\n");
pout.write("<h1>Rego Servlet</h1>\n");
pout.write("<table width=\"95%\">");
pout.write("<tr>\n");
pout.write("<th align=\"right\">getMethod:&nbsp;</th>");
pout.write("<td>" + notag(request.getMethod())+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getContentLength:&nbsp;</th>");
pout.write("<td>"+Integer.toString(request.getContentLength())+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getContentType:&nbsp;</th>");
pout.write("<td>"+notag(request.getContentType())+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getRequestURI:&nbsp;</th>");
pout.write("<td>"+notag(request.getRequestURI())+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getRequestURL:&nbsp;</th>");
pout.write("<td>"+notag(request.getRequestURL().toString())+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getContextPath:&nbsp;</th>");
pout.write("<td>"+request.getContextPath()+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getServletPath:&nbsp;</th>");
pout.write("<td>"+notag(request.getServletPath())+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getPathInfo:&nbsp;</th>");
pout.write("<td>"+notag(request.getPathInfo())+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getPathTranslated:&nbsp;</th>");
pout.write("<td>"+notag(request.getPathTranslated())+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getQueryString:&nbsp;</th>");
pout.write("<td>"+notag(request.getQueryString())+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getProtocol:&nbsp;</th>");
pout.write("<td>"+request.getProtocol()+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getScheme:&nbsp;</th>");
pout.write("<td>"+request.getScheme()+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getServerName:&nbsp;</th>");
pout.write("<td>"+notag(request.getServerName())+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getServerPort:&nbsp;</th>");
pout.write("<td>"+Integer.toString(request.getServerPort())+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getLocalName:&nbsp;</th>");
pout.write("<td>"+request.getLocalName()+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getLocalAddr:&nbsp;</th>");
pout.write("<td>"+request.getLocalAddr()+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getLocalPort:&nbsp;</th>");
pout.write("<td>"+Integer.toString(request.getLocalPort())+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getRemoteUser:&nbsp;</th>");
pout.write("<td>"+request.getRemoteUser()+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getUserPrincipal:&nbsp;</th>");
pout.write("<td>"+request.getUserPrincipal()+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getRemoteAddr:&nbsp;</th>");
pout.write("<td>"+request.getRemoteAddr()+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getRemoteHost:&nbsp;</th>");
pout.write("<td>"+request.getRemoteHost()+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getRemotePort:&nbsp;</th>");
pout.write("<td>"+request.getRemotePort()+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">getRequestedSessionId:&nbsp;</th>");
pout.write("<td>"+request.getRequestedSessionId()+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">isSecure():&nbsp;</th>");
pout.write("<td>"+request.isSecure()+"</td>");
pout.write("</tr><tr>\n");
pout.write("<th align=\"right\">isUserInRole(admin):&nbsp;</th>");
pout.write("<td>"+request.isUserInRole("admin")+"</td>");
pout.write("</tr></table>");
}
catch (Exception e)
{
getServletContext().log("dump "+e);
}
pout.write("</body>\n</html>\n");
pout.close();
}
/* ------------------------------------------------------------ */
@Override
public String getServletInfo()
{
return "Rego Servlet";
}
/* ------------------------------------------------------------ */
@Override
public synchronized void destroy()
{
}
private String notag(String s)
{
if (s==null)
return "null";
s=StringUtil.replace(s,"&","&amp;");
s=StringUtil.replace(s,"<","&lt;");
s=StringUtil.replace(s,">","&gt;");
return s;
}
}

View File

@ -18,6 +18,7 @@
package com.acme;
import javax.servlet.DispatcherType;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
@ -26,6 +27,12 @@ import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.ServletRegistration;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletSecurityElement;
import javax.servlet.HttpConstraintElement;
import javax.servlet.HttpMethodConstraintElement;
import javax.servlet.annotation.ServletSecurity;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionAttributeListener;
@ -33,6 +40,9 @@ import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.util.EnumSet;
import java.util.Set;
public class TestListener implements HttpSessionListener, HttpSessionAttributeListener, HttpSessionActivationListener, ServletContextListener, ServletContextAttributeListener, ServletRequestListener, ServletRequestAttributeListener
{
public void attributeAdded(HttpSessionBindingEvent se)
@ -62,16 +72,30 @@ public class TestListener implements HttpSessionListener, HttpSessionAttributeL
public void contextInitialized(ServletContextEvent sce)
{
/* TODO for servlet 3.0
* FilterRegistration registration=context.addFilter("TestFilter",TestFilter.class.getName());
//configure programmatic security
ServletRegistration.Dynamic rego = sce.getServletContext().addServlet("RegoTest", RegTest.class.getName());
rego.addMapping("/rego/*");
HttpConstraintElement constraintElement = new HttpConstraintElement(ServletSecurity.EmptyRoleSemantic.PERMIT,
ServletSecurity.TransportGuarantee.NONE, new String[]{"admin"});
ServletSecurityElement securityElement = new ServletSecurityElement(constraintElement, null);
Set<String> unchanged = rego.setServletSecurity(securityElement);
System.err.println("Security constraints registered: "+unchanged.isEmpty());
//Test that a security constraint from web.xml can't be overridden programmatically
ServletRegistration.Dynamic rego2 = sce.getServletContext().addServlet("RegoTest2", RegTest.class.getName());
rego2.addMapping("/rego2/*");
securityElement = new ServletSecurityElement(constraintElement, null);
unchanged = rego2.setServletSecurity(securityElement);
System.err.println("Overridding web.xml constraints not possible:" +!unchanged.isEmpty());
/* For servlet 3.0 */
FilterRegistration.Dynamic registration = sce.getServletContext().addFilter("TestFilter",TestFilter.class.getName());
registration.setInitParameter("remote", "false");
registration.setAsyncSupported(true);
registration.addMappingForUrlPatterns(
EnumSet.of(DispatcherType.ERROR,DispatcherType.ASYNC,DispatcherType.FORWARD,DispatcherType.INCLUDE,DispatcherType.REQUEST),
true,
new String[]{"/dump/*","/dispatch/*","*.dump"});
*/
new String[]{"/*"});
}
public void contextDestroyed(ServletContextEvent sce)

View File

@ -18,20 +18,6 @@
<listener-class>com.acme.TestListener</listener-class>
</listener>
<filter>
<filter-name>TestFilter</filter-name>
<filter-class>com.acme.TestFilter</filter-class>
<async-support>true</async-support>
<init-param>
<param-name>remote</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>QoSFilter</filter-name>
@ -120,7 +106,6 @@
</filter-mapping>
-->
<servlet>
<servlet-name>Hello</servlet-name>
<servlet-class>com.acme.HelloWorld</servlet-class>
@ -275,6 +260,18 @@
<location>/error404.html</location>
</error-page>
<security-constraint>
<web-resource-collection>
<web-resource-name>Rego2</web-resource-name>
<url-pattern>/rego2/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>server-administrator</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Auth2</web-resource-name>

View File

@ -18,6 +18,8 @@ This page contains several links to test the authentication constraints:
<li><a href="dump/auth/info">dump/auth/*</a> - Authenticated any user</li>
<li><a href="dump/auth/admin/info">dump/auth/admin/*</a> - Authenticated admin role (<a href="session/?Action=Invalidate">click</a> to invalidate session)</li>
<li><a href="dump/auth/ssl/info">dump/auth/ssl/*</a> - Confidential</li>
<li><a href="rego/info">rego/info/*</a> - Authenticated admin role from programmatic security (<a href="session/?Action=Invalidate">click</a> to invalidate session)</li>
<li><a href="rego2/info">rego2/info/*</a> - Authenticated servlet-administrator role from programmatic security (login as admin/admin, <a href="session/?Action=Invalidate">click</a> to invalidate session)</li>
</ul>
<p/>
<p>