diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/servlet/PathRequest.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/servlet/PathRequest.java
new file mode 100644
index 00000000000..a87541557f4
--- /dev/null
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/servlet/PathRequest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012-2018 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.autoconfigure.security.servlet;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.boot.autoconfigure.h2.H2ConsoleProperties;
+import org.springframework.boot.autoconfigure.security.StaticResourceLocation;
+import org.springframework.boot.security.servlet.ApplicationContextRequestMatcher;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+
+/**
+ * Factory that can be used to create a {@link RequestMatcher} for commonly used paths.
+ *
+ * @author Madhura Bhave
+ * @author Phillip Webb
+ * @since 2.0.0
+ */
+public final class PathRequest {
+
+ private PathRequest() {
+ }
+
+ /**
+ * Returns a {@link StaticResourceRequest} that can be used to create a matcher for
+ * {@link StaticResourceLocation Locations}.
+ * @return a {@link StaticResourceRequest}
+ */
+ public static StaticResourceRequest toStaticResources() {
+ return StaticResourceRequest.get();
+ }
+
+ /**
+ * Returns a matcher that includes the H2 console location. For example:
+ * PathRequest.toH2Console()
+ *
+ * @return the configured {@link RequestMatcher}
+ */
+ public static H2ConsoleRequestMatcher toH2Console() {
+ return new H2ConsoleRequestMatcher();
+ }
+
+ /**
+ * The request matcher used to match against h2 console path.
+ */
+ public static final class H2ConsoleRequestMatcher
+ extends ApplicationContextRequestMatcher {
+
+ private RequestMatcher delegate;
+
+ private H2ConsoleRequestMatcher() {
+ super(H2ConsoleProperties.class);
+ }
+
+ @Override
+ protected void initialized(H2ConsoleProperties h2ConsoleProperties) {
+ this.delegate = new AntPathRequestMatcher(h2ConsoleProperties.getPath());
+ }
+
+ @Override
+ protected boolean matches(HttpServletRequest request, H2ConsoleProperties context) {
+ return this.delegate.matches(request);
+ }
+
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/servlet/StaticResourceRequest.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/servlet/StaticResourceRequest.java
index d4ab0f2f0e3..a3954fd4d9c 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/servlet/StaticResourceRequest.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/servlet/StaticResourceRequest.java
@@ -34,15 +34,18 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
/**
- * Factory that can be used to create a {@link RequestMatcher} for static resources in
- * commonly used locations.
+ * Used to create a {@link RequestMatcher} for static resources in
+ * commonly used locations. Returned by {@link PathRequest#toStaticResources()}.
*
* @author Madhura Bhave
* @author Phillip Webb
* @since 2.0.0
+ * @see PathRequest
*/
public final class StaticResourceRequest {
+ private static final StaticResourceRequest INSTANCE = new StaticResourceRequest();
+
private StaticResourceRequest() {
}
@@ -52,41 +55,49 @@ public final class StaticResourceRequest {
* {@link StaticResourceRequestMatcher#excluding(StaticResourceLocation, StaticResourceLocation...)
* excluding} method can be used to remove specific locations if required. For
* example:
- * StaticResourceRequest.toCommonLocations().excluding(StaticResourceLocation.CSS)
+ * StaticResourceRequest.atCommonLocations().excluding(StaticResourceLocation.CSS)
*
* @return the configured {@link RequestMatcher}
*/
- public static StaticResourceRequestMatcher toCommonLocations() {
- return to(EnumSet.allOf(StaticResourceLocation.class));
+ public StaticResourceRequestMatcher atCommonLocations() {
+ return at(EnumSet.allOf(StaticResourceLocation.class));
}
/**
* Returns a matcher that includes the specified {@link StaticResourceLocation
* Locations}. For example:
- * StaticResourceRequest.to(StaticResourceLocation.CSS, StaticResourceLocation.JAVA_SCRIPT)
+ * StaticResourceRequest.at(StaticResourceLocation.CSS, StaticResourceLocation.JAVA_SCRIPT)
*
* @param first the first location to include
* @param rest additional locations to include
* @return the configured {@link RequestMatcher}
*/
- public static StaticResourceRequestMatcher to(StaticResourceLocation first,
+ public StaticResourceRequestMatcher at(StaticResourceLocation first,
StaticResourceLocation... rest) {
- return to(EnumSet.of(first, rest));
+ return at(EnumSet.of(first, rest));
}
/**
* Returns a matcher that includes the specified {@link StaticResourceLocation
* Locations}. For example:
- * StaticResourceRequest.to(locations)
+ * StaticResourceRequest.at(locations)
*
* @param locations the locations to include
* @return the configured {@link RequestMatcher}
*/
- public static StaticResourceRequestMatcher to(Set locations) {
+ public StaticResourceRequestMatcher at(Set locations) {
Assert.notNull(locations, "Locations must not be null");
return new StaticResourceRequestMatcher(new LinkedHashSet<>(locations));
}
+ /**
+ * Return the static resource request.
+ * @return the static resource request
+ */
+ static StaticResourceRequest get() {
+ return INSTANCE;
+ }
+
/**
* The request matcher used to match against resource {@link StaticResourceLocation
* Locations}.
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/servlet/PathRequestTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/servlet/PathRequestTests.java
new file mode 100644
index 00000000000..13c6f0c0a90
--- /dev/null
+++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/servlet/PathRequestTests.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2012-2018 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.autoconfigure.security.servlet;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.assertj.core.api.AssertDelegateTarget;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import org.springframework.boot.autoconfigure.web.ServerProperties;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link PathRequest}.
+ *
+ * @author Madhura Bhave
+ */
+public class PathRequestTests {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void toStaticResourcesShouldReturnStaticResourceRequest() {
+ assertThat(PathRequest.toStaticResources()).isInstanceOf(StaticResourceRequest.class);
+ }
+
+ @Test
+ public void toH2ConsoleShouldMatchH2ConsolePath() {
+ RequestMatcher matcher = PathRequest.toH2Console();
+ assertMatcher(matcher).matches("/h2-console");
+ assertMatcher(matcher).doesNotMatch("/js/file.js");
+ }
+
+ private RequestMatcherAssert assertMatcher(RequestMatcher matcher) {
+ StaticWebApplicationContext context = new StaticWebApplicationContext();
+ context.registerBean(ServerProperties.class);
+ return assertThat(new RequestMatcherAssert(context, matcher));
+ }
+
+ private static class RequestMatcherAssert implements AssertDelegateTarget {
+
+ private final WebApplicationContext context;
+
+ private final RequestMatcher matcher;
+
+ RequestMatcherAssert(WebApplicationContext context, RequestMatcher matcher) {
+ this.context = context;
+ this.matcher = matcher;
+ }
+
+ public void matches(String path) {
+ matches(mockRequest(path));
+ }
+
+ private void matches(HttpServletRequest request) {
+ assertThat(this.matcher.matches(request))
+ .as("Matches " + getRequestPath(request)).isTrue();
+ }
+
+ public void doesNotMatch(String path) {
+ doesNotMatch(mockRequest(path));
+ }
+
+ private void doesNotMatch(HttpServletRequest request) {
+ assertThat(this.matcher.matches(request))
+ .as("Does not match " + getRequestPath(request)).isFalse();
+ }
+
+ private MockHttpServletRequest mockRequest(String path) {
+ MockServletContext servletContext = new MockServletContext();
+ servletContext.setAttribute(
+ WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
+ this.context);
+ MockHttpServletRequest request = new MockHttpServletRequest(servletContext);
+ request.setPathInfo(path);
+ return request;
+ }
+
+ private String getRequestPath(HttpServletRequest request) {
+ String url = request.getServletPath();
+ if (request.getPathInfo() != null) {
+ url += request.getPathInfo();
+ }
+ return url;
+ }
+
+ }
+
+}
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/servlet/StaticResourceRequestTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/servlet/StaticResourceRequestTests.java
index c41c13ed9c7..50654bbec10 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/servlet/StaticResourceRequestTests.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/servlet/StaticResourceRequestTests.java
@@ -16,8 +16,6 @@
package org.springframework.boot.autoconfigure.security.servlet;
-import java.util.Set;
-
import javax.servlet.http.HttpServletRequest;
import org.assertj.core.api.AssertDelegateTarget;
@@ -43,12 +41,14 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
public class StaticResourceRequestTests {
+ private StaticResourceRequest resourceRequest = StaticResourceRequest.get();
+
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
- public void toCommonLocationsShouldMatchCommonLocations() {
- RequestMatcher matcher = StaticResourceRequest.toCommonLocations();
+ public void atCommonLocationsShouldMatchCommonLocations() {
+ RequestMatcher matcher = this.resourceRequest.atCommonLocations();
assertMatcher(matcher).matches("/css/file.css");
assertMatcher(matcher).matches("/js/file.js");
assertMatcher(matcher).matches("/images/file.css");
@@ -58,42 +58,42 @@ public class StaticResourceRequestTests {
}
@Test
- public void toCommonLocationsWithExcludeShouldNotMatchExcluded() {
- RequestMatcher matcher = StaticResourceRequest.toCommonLocations()
+ public void atCommonLocationsWithExcludeShouldNotMatchExcluded() {
+ RequestMatcher matcher = this.resourceRequest.atCommonLocations()
.excluding(StaticResourceLocation.CSS);
assertMatcher(matcher).doesNotMatch("/css/file.css");
assertMatcher(matcher).matches("/js/file.js");
}
@Test
- public void toLocationShouldMatchLocation() {
- RequestMatcher matcher = StaticResourceRequest.to(StaticResourceLocation.CSS);
+ public void atLocationShouldMatchLocation() {
+ RequestMatcher matcher = this.resourceRequest.at(StaticResourceLocation.CSS);
assertMatcher(matcher).matches("/css/file.css");
assertMatcher(matcher).doesNotMatch("/js/file.js");
}
@Test
- public void toLocationWhenHasServletPathShouldMatchLocation() {
+ public void atLocationWhenHasServletPathShouldMatchLocation() {
ServerProperties serverProperties = new ServerProperties();
serverProperties.getServlet().setPath("/foo");
- RequestMatcher matcher = StaticResourceRequest.to(StaticResourceLocation.CSS);
+ RequestMatcher matcher = this.resourceRequest.at(StaticResourceLocation.CSS);
assertMatcher(matcher, serverProperties).matches("/foo", "/css/file.css");
assertMatcher(matcher, serverProperties).doesNotMatch("/foo", "/js/file.js");
}
@Test
- public void toLocationsFromSetWhenSetIsNullShouldThrowException() {
+ public void atLocationsFromSetWhenSetIsNullShouldThrowException() {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("Locations must not be null");
- StaticResourceRequest.to((Set) null);
+ this.resourceRequest.at(null);
}
@Test
public void excludeFromSetWhenSetIsNullShouldThrowException() {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("Locations must not be null");
- StaticResourceRequest.toCommonLocations()
- .excluding((Set) null);
+ this.resourceRequest.atCommonLocations()
+ .excluding(null);
}
private RequestMatcherAssert assertMatcher(RequestMatcher matcher) {
diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
index b5541089b9c..a14c1b3d5dc 100644
--- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
+++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
@@ -3013,7 +3013,7 @@ Access rules can be overridden by adding a custom `WebSecurityConfigurerAdapter`
Boot provides convenience methods that can be used to override access rules for actuator
endpoints and static resources. `EndpointRequest` can be used to create a `RequestMatcher`
that is based on the `management.endpoints.web.base-path` property.
-`StaticResourceRequest` can be used to create a `RequestMatcher` for static resources in
+`PathRequest` can be used to create a `RequestMatcher` for resources in
commonly used locations.
diff --git a/spring-boot-samples/spring-boot-sample-actuator-custom-security/src/main/java/sample/actuator/customsecurity/SecurityConfiguration.java b/spring-boot-samples/spring-boot-sample-actuator-custom-security/src/main/java/sample/actuator/customsecurity/SecurityConfiguration.java
index f722f449033..53967fd1ab8 100644
--- a/spring-boot-samples/spring-boot-sample-actuator-custom-security/src/main/java/sample/actuator/customsecurity/SecurityConfiguration.java
+++ b/spring-boot-samples/spring-boot-sample-actuator-custom-security/src/main/java/sample/actuator/customsecurity/SecurityConfiguration.java
@@ -17,7 +17,7 @@
package sample.actuator.customsecurity;
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
-import org.springframework.boot.autoconfigure.security.servlet.StaticResourceRequest;
+import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@@ -43,7 +43,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
http.authorizeRequests()
.requestMatchers(EndpointRequest.to("health", "info")).permitAll()
.requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole("ACTUATOR")
- .requestMatchers(StaticResourceRequest.toCommonLocations()).permitAll()
+ .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.antMatchers("/foo").permitAll()
.antMatchers("/**").hasRole("USER")
.and()
diff --git a/spring-boot-samples/spring-boot-sample-web-secure/src/main/java/sample/web/secure/SampleWebSecureApplication.java b/spring-boot-samples/spring-boot-sample-web-secure/src/main/java/sample/web/secure/SampleWebSecureApplication.java
index 3b0d66365a4..b8962b9e082 100644
--- a/spring-boot-samples/spring-boot-sample-web-secure/src/main/java/sample/web/secure/SampleWebSecureApplication.java
+++ b/spring-boot-samples/spring-boot-sample-web-secure/src/main/java/sample/web/secure/SampleWebSecureApplication.java
@@ -20,7 +20,7 @@ import java.util.Date;
import java.util.Map;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.autoconfigure.security.servlet.StaticResourceRequest;
+import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@@ -64,7 +64,7 @@ public class SampleWebSecureApplication implements WebMvcConfigurer {
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.authorizeRequests()
- .requestMatchers(StaticResourceRequest.toCommonLocations()).permitAll()
+ .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.anyRequest().fullyAuthenticated()
.and()
.formLogin().loginPage("/login").failureUrl("/login?error").permitAll()