DispatcherPortlet's default resource serving explicitly prevents access to WEB-INF and META-INF (SPR-7540)

This commit is contained in:
Juergen Hoeller 2010-10-02 00:03:09 +00:00
parent aac2de9221
commit 40fa8afce4
4 changed files with 83 additions and 18 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -23,7 +23,6 @@ import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.Portlet;
import javax.portlet.PortletContext;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
@ -33,6 +32,7 @@ import javax.portlet.ResourceServingPortlet;
import org.springframework.web.portlet.HandlerAdapter;
import org.springframework.web.portlet.ModelAndView;
import org.springframework.web.portlet.context.PortletContextAware;
import org.springframework.web.portlet.util.PortletUtils;
/**
* Adapter to use the Portlet interface with the generic DispatcherPortlet.
@ -92,13 +92,8 @@ public class SimplePortletHandlerAdapter implements HandlerAdapter, PortletConte
((ResourceServingPortlet) handler).serveResource(request, response);
}
else {
// equivalent to Portlet 2.0 GenericPortlet
if (request.getResourceID() != null) {
PortletRequestDispatcher rd = this.portletContext.getRequestDispatcher(request.getResourceID());
if (rd != null) {
rd.forward(request, response);
}
}
// roughly equivalent to Portlet 2.0 GenericPortlet
PortletUtils.serveResource(request, response, this.portletContext);
}
return null;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,7 +21,6 @@ import javax.portlet.ActionResponse;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.PortletContext;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
@ -30,6 +29,7 @@ import javax.portlet.ResourceResponse;
import org.springframework.web.portlet.HandlerAdapter;
import org.springframework.web.portlet.ModelAndView;
import org.springframework.web.portlet.context.PortletContextAware;
import org.springframework.web.portlet.util.PortletUtils;
/**
* Adapter to use the Controller workflow interface with the generic DispatcherPortlet.
@ -78,12 +78,7 @@ public class SimpleControllerHandlerAdapter implements HandlerAdapter, PortletCo
}
else {
// equivalent to Portlet 2.0 GenericPortlet
if (request.getResourceID() != null) {
PortletRequestDispatcher rd = this.portletContext.getRequestDispatcher(request.getResourceID());
if (rd != null) {
rd.forward(request, response);
}
}
PortletUtils.serveResource(request, response, this.portletContext);
return null;
}
}

View File

@ -18,6 +18,7 @@ package org.springframework.web.portlet.util;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
@ -25,11 +26,16 @@ import java.util.TreeMap;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletContext;
import javax.portlet.PortletException;
import javax.portlet.PortletRequest;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.PortletSession;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import javax.servlet.http.Cookie;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.util.WebUtils;
/**
@ -442,11 +448,47 @@ public abstract class PortletUtils {
*/
public static void clearAllRenderParameters(ActionResponse response) {
try {
response.setRenderParameters(new HashMap());
response.setRenderParameters(new HashMap<String, String[]>(0));
}
catch (IllegalStateException ex) {
// Ignore in case sendRedirect was already set.
}
}
/**
* Serve the resource as specified in the given request to the given response,
* using the PortletContext's request dispatcher.
* <p>This is roughly equivalent to Portlet 2.0 GenericPortlet.
* @param request the current resource request
* @param response the current resource response
* @param context the current Portlet's PortletContext
* @throws PortletException propagated from Portlet API's forward method
* @throws IOException propagated from Portlet API's forward method
*/
public static void serveResource(ResourceRequest request, ResourceResponse response, PortletContext context)
throws PortletException, IOException {
String id = request.getResourceID();
if (id != null) {
if (!PortletUtils.isProtectedResource(id)) {
PortletRequestDispatcher rd = context.getRequestDispatcher(id);
if (rd != null) {
rd.forward(request, response);
return;
}
}
response.setProperty(ResourceResponse.HTTP_STATUS_CODE, "404");
}
}
/**
* Check whether the specified path indicates a resource in the protected
* WEB-INF or META-INF directories.
* @param path the path to check
*/
private static boolean isProtectedResource(String path) {
return (StringUtils.startsWithIgnoreCase(path, "/WEB-INF") ||
StringUtils.startsWithIgnoreCase(path, "/META-INF"));
}
}

View File

@ -33,6 +33,7 @@ import javax.portlet.PortletRequest;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceResponse;
import javax.portlet.StateAwareResponse;
import javax.portlet.WindowState;
import javax.servlet.http.Cookie;
@ -117,6 +118,38 @@ public class Portlet20AnnotationControllerTests {
assertEquals("test", response.getContentAsString());
}
@Test
public void standardHandleMethodWithResources() throws Exception {
DispatcherPortlet portlet = new DispatcherPortlet() {
protected ApplicationContext createPortletApplicationContext(ApplicationContext parent) throws BeansException {
StaticPortletApplicationContext wac = new StaticPortletApplicationContext();
wac.setPortletConfig(getPortletConfig());
wac.registerBeanDefinition("controller", new RootBeanDefinition(MyController.class));
wac.refresh();
return wac;
}
};
portlet.init(new MockPortletConfig());
MockResourceRequest resourceRequest = new MockResourceRequest("/resource1");
MockResourceResponse resourceResponse = new MockResourceResponse();
portlet.serveResource(resourceRequest, resourceResponse);
assertEquals("/resource1", resourceResponse.getForwardedUrl());
assertNull(resourceResponse.getProperty(ResourceResponse.HTTP_STATUS_CODE));
resourceRequest = new MockResourceRequest("/WEB-INF/resource2");
resourceResponse = new MockResourceResponse();
portlet.serveResource(resourceRequest, resourceResponse);
assertNull(resourceResponse.getForwardedUrl());
assertEquals("404", resourceResponse.getProperty(ResourceResponse.HTTP_STATUS_CODE));
resourceRequest = new MockResourceRequest("/META-INF/resource3");
resourceResponse = new MockResourceResponse();
portlet.serveResource(resourceRequest, resourceResponse);
assertNull(resourceResponse.getForwardedUrl());
assertEquals("404", resourceResponse.getProperty(ResourceResponse.HTTP_STATUS_CODE));
}
@Test
public void adaptedHandleMethods() throws Exception {
doTestAdaptedHandleMethods(MyAdaptedController.class);