Do not expose servlet locations in WebFlux

The `spring.resources.static-locations` key (see `ResourceProperties`)
lists many locations by default, including `"classpath:/static"` and
`"/"`. The latter is about exposing resources located in the root
servlet location.

Reactive web applications don't depend on a Servlet-related
`ApplicationContext`/`ResourceLoader`, so `"/"` is then resolved as
`"classpath:/"`, which exposes the whole classpath.

To avoid such situations, the `GenericReactiveWebApplicationContext`
overrides the `getResourceByPath(String path)` method and always returns
non existent resources if the path starts with `"/"`.

Fixes gh-8485
pull/8718/merge
Brian Clozel 8 years ago
parent 00021dcd75
commit 2ab1191f8d

@ -16,13 +16,20 @@
package org.springframework.boot.web.reactive.context;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.io.AbstractResource;
import org.springframework.core.io.Resource;
/**
* Subclass of {@link AnnotationConfigApplicationContext}, suitable for reactive web
* environments.
*
* @author Stephane Nicoll
* @author Brian Clozel
* @since 2.0.0
*/
public class GenericReactiveWebApplicationContext extends
@ -30,6 +37,8 @@ public class GenericReactiveWebApplicationContext extends
private String namespace;
private final NonExistentResource nonExistentResource = new NonExistentResource();
public GenericReactiveWebApplicationContext() {
super();
}
@ -48,4 +57,45 @@ public class GenericReactiveWebApplicationContext extends
return this.namespace;
}
@Override
protected Resource getResourceByPath(String path) {
// No ServletContext is available
if (path.startsWith("/")) {
return this.nonExistentResource;
}
else {
return super.getResourceByPath(path);
}
}
/**
* Resource implementation that replaces the
* {@link org.springframework.web.context.support.ServletContextResource}
* in a reactive web application.
*
* <p>{@link #exists()} always returns null in order to avoid exposing
* the whole classpath in a non-servlet environment.
*/
class NonExistentResource extends AbstractResource {
@Override
public boolean exists() {
return false;
}
@Override
public Resource createRelative(String relativePath) throws IOException {
return this;
}
@Override
public String getDescription() {
return "NonExistentResource";
}
@Override
public InputStream getInputStream() throws IOException {
throw new FileNotFoundException(this.getDescription() + " cannot be opened because it does not exist");
}
}
}

@ -0,0 +1,40 @@
/*
* Copyright 2012-2017 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.web.reactive.context;
import org.junit.Test;
import org.springframework.core.io.Resource;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link GenericReactiveWebApplicationContext}
*
* @author Brian Clozel
*/
public class GenericReactiveWebApplicationContextTests {
@Test
public void getResourceByPath() throws Exception {
GenericReactiveWebApplicationContext context = new GenericReactiveWebApplicationContext();
Resource rootResource = context.getResourceByPath("/");
assertThat(rootResource.exists()).isFalse();
assertThat(rootResource.createRelative("application.properties").exists()).isFalse();
}
}
Loading…
Cancel
Save