Commit 134628a6 authored by Madhura Bhave's avatar Madhura Bhave

Add PathRequest to reactive security for parity

parent e80c22cb
/*
* 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.reactive;
import org.springframework.boot.autoconfigure.security.StaticResourceLocation;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
/**
* Factory that can be used to create a {@link ServerWebExchangeMatcher} for commonly used paths.
*
* @author Madhura Bhave
* @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();
}
}
...@@ -33,14 +33,17 @@ import org.springframework.util.Assert; ...@@ -33,14 +33,17 @@ import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebExchange;
/** /**
* Factory that can be used to create a {@link ServerWebExchangeMatcher} for static * Used to create a {@link ServerWebExchangeMatcher} for static resources in
* resources in commonly used locations. * commonly used locations. Returned by {@link PathRequest#toStaticResources()}.
* *
* @author Madhura Bhave * @author Madhura Bhave
* @since 2.0.0 * @since 2.0.0
* @see PathRequest
*/ */
public final class StaticResourceRequest { public final class StaticResourceRequest {
private static final StaticResourceRequest INSTANCE = new StaticResourceRequest();
private StaticResourceRequest() { private StaticResourceRequest() {
} }
...@@ -50,42 +53,50 @@ public final class StaticResourceRequest { ...@@ -50,42 +53,50 @@ public final class StaticResourceRequest {
* {@link StaticResourceServerWebExchange#excluding(StaticResourceLocation, StaticResourceLocation...) * {@link StaticResourceServerWebExchange#excluding(StaticResourceLocation, StaticResourceLocation...)
* excluding} method can be used to remove specific locations if required. For * excluding} method can be used to remove specific locations if required. For
* example: <pre class="code"> * example: <pre class="code">
* StaticResourceRequest.toCommonLocations().excluding(StaticResourceLocation.CSS) * StaticResourceRequest.atCommonLocations().excluding(StaticResourceLocation.CSS)
* </pre> * </pre>
* @return the configured {@link ServerWebExchangeMatcher} * @return the configured {@link ServerWebExchangeMatcher}
*/ */
public static StaticResourceServerWebExchange toCommonLocations() { public StaticResourceServerWebExchange atCommonLocations() {
return to(EnumSet.allOf(StaticResourceLocation.class)); return at(EnumSet.allOf(StaticResourceLocation.class));
} }
/** /**
* Returns a matcher that includes the specified {@link StaticResourceLocation * Returns a matcher that includes the specified {@link StaticResourceLocation
* Locations}. For example: <pre class="code"> * Locations}. For example: <pre class="code">
* to(StaticResourceLocation.CSS, StaticResourceLocation.JAVA_SCRIPT) * at(StaticResourceLocation.CSS, StaticResourceLocation.JAVA_SCRIPT)
* </pre> * </pre>
* @param first the first location to include * @param first the first location to include
* @param rest additional locations to include * @param rest additional locations to include
* @return the configured {@link ServerWebExchangeMatcher} * @return the configured {@link ServerWebExchangeMatcher}
*/ */
public static StaticResourceServerWebExchange to(StaticResourceLocation first, public StaticResourceServerWebExchange at(StaticResourceLocation first,
StaticResourceLocation... rest) { StaticResourceLocation... rest) {
return to(EnumSet.of(first, rest)); return at(EnumSet.of(first, rest));
} }
/** /**
* Returns a matcher that includes the specified {@link StaticResourceLocation * Returns a matcher that includes the specified {@link StaticResourceLocation
* Locations}. For example: <pre class="code"> * Locations}. For example: <pre class="code">
* to(locations) * at(locations)
* </pre> * </pre>
* @param locations the locations to include * @param locations the locations to include
* @return the configured {@link ServerWebExchangeMatcher} * @return the configured {@link ServerWebExchangeMatcher}
*/ */
public static StaticResourceServerWebExchange to( public StaticResourceServerWebExchange at(
Set<StaticResourceLocation> locations) { Set<StaticResourceLocation> locations) {
Assert.notNull(locations, "Locations must not be null"); Assert.notNull(locations, "Locations must not be null");
return new StaticResourceServerWebExchange(new LinkedHashSet<>(locations)); return new StaticResourceServerWebExchange(new LinkedHashSet<>(locations));
} }
/**
* Return the static resource request.
* @return the static resource request
*/
static StaticResourceRequest get() {
return INSTANCE;
}
/** /**
* The server web exchange matcher used to match against resource * The server web exchange matcher used to match against resource
* {@link StaticResourceLocation Locations}. * {@link StaticResourceLocation Locations}.
......
/*
* 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.reactive;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link PathRequest}.
*
* @author Madhura Bhave
*/
public class PathRequestTests {
@Test
public void toStaticResourcesShouldReturnStaticResourceRequest() {
assertThat(PathRequest.toStaticResources()).isInstanceOf(StaticResourceRequest.class);
}
}
...@@ -44,12 +44,14 @@ import static org.mockito.Mockito.mock; ...@@ -44,12 +44,14 @@ import static org.mockito.Mockito.mock;
*/ */
public class StaticResourceRequestTests { public class StaticResourceRequestTests {
private StaticResourceRequest resourceRequest = StaticResourceRequest.get();
@Rule @Rule
public ExpectedException thrown = ExpectedException.none(); public ExpectedException thrown = ExpectedException.none();
@Test @Test
public void toCommonLocationsShouldMatchCommonLocations() { public void atCommonLocationsShouldMatchCommonLocations() {
ServerWebExchangeMatcher matcher = StaticResourceRequest.toCommonLocations(); ServerWebExchangeMatcher matcher = this.resourceRequest.atCommonLocations();
assertMatcher(matcher).matches("/css/file.css"); assertMatcher(matcher).matches("/css/file.css");
assertMatcher(matcher).matches("/js/file.js"); assertMatcher(matcher).matches("/js/file.js");
assertMatcher(matcher).matches("/images/file.css"); assertMatcher(matcher).matches("/images/file.css");
...@@ -59,33 +61,33 @@ public class StaticResourceRequestTests { ...@@ -59,33 +61,33 @@ public class StaticResourceRequestTests {
} }
@Test @Test
public void toCommonLocationsWithExcludeShouldNotMatchExcluded() { public void atCommonLocationsWithExcludeShouldNotMatchExcluded() {
ServerWebExchangeMatcher matcher = StaticResourceRequest.toCommonLocations() ServerWebExchangeMatcher matcher = this.resourceRequest.atCommonLocations()
.excluding(StaticResourceLocation.CSS); .excluding(StaticResourceLocation.CSS);
assertMatcher(matcher).doesNotMatch("/css/file.css"); assertMatcher(matcher).doesNotMatch("/css/file.css");
assertMatcher(matcher).matches("/js/file.js"); assertMatcher(matcher).matches("/js/file.js");
} }
@Test @Test
public void toLocationShouldMatchLocation() { public void atLocationShouldMatchLocation() {
ServerWebExchangeMatcher matcher = StaticResourceRequest ServerWebExchangeMatcher matcher = this.resourceRequest
.to(StaticResourceLocation.CSS); .at(StaticResourceLocation.CSS);
assertMatcher(matcher).matches("/css/file.css"); assertMatcher(matcher).matches("/css/file.css");
assertMatcher(matcher).doesNotMatch("/js/file.js"); assertMatcher(matcher).doesNotMatch("/js/file.js");
} }
@Test @Test
public void toLocationsFromSetWhenSetIsNullShouldThrowException() { public void atLocationsFromSetWhenSetIsNullShouldThrowException() {
this.thrown.expect(IllegalArgumentException.class); this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("Locations must not be null"); this.thrown.expectMessage("Locations must not be null");
StaticResourceRequest.to(null); this.resourceRequest.at(null);
} }
@Test @Test
public void excludeFromSetWhenSetIsNullShouldThrowException() { public void excludeFromSetWhenSetIsNullShouldThrowException() {
this.thrown.expect(IllegalArgumentException.class); this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("Locations must not be null"); this.thrown.expectMessage("Locations must not be null");
StaticResourceRequest.toCommonLocations().excluding(null); this.resourceRequest.atCommonLocations().excluding(null);
} }
private StaticResourceRequestTests.RequestMatcherAssert assertMatcher( private StaticResourceRequestTests.RequestMatcherAssert assertMatcher(
......
...@@ -3035,7 +3035,7 @@ Boot provides convenience methods that can be used to override access rules for ...@@ -3035,7 +3035,7 @@ Boot provides convenience methods that can be used to override access rules for
endpoints and static resources. `EndpointRequest` can be used to create a `ServerWebExchangeMatcher` endpoints and static resources. `EndpointRequest` can be used to create a `ServerWebExchangeMatcher`
that is based on the `management.endpoints.web.base-path` property. that is based on the `management.endpoints.web.base-path` property.
`StaticResourceRequest` can be used to create a `ServerWebExchangeMatcher` for static resources in `PathRequest` can be used to create a `ServerWebExchangeMatcher` for resources in
commonly used locations. commonly used locations.
......
...@@ -23,6 +23,7 @@ import org.junit.runner.RunWith; ...@@ -23,6 +23,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.security.reactive.EndpointRequest; import org.springframework.boot.actuate.autoconfigure.security.reactive.EndpointRequest;
import org.springframework.boot.autoconfigure.security.reactive.PathRequest;
import org.springframework.boot.autoconfigure.security.reactive.StaticResourceRequest; import org.springframework.boot.autoconfigure.security.reactive.StaticResourceRequest;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
...@@ -101,7 +102,7 @@ public class SampleSecureWebFluxCustomSecurityTests { ...@@ -101,7 +102,7 @@ public class SampleSecureWebFluxCustomSecurityTests {
http.authorizeExchange().matchers(EndpointRequest.to("health", "info")) http.authorizeExchange().matchers(EndpointRequest.to("health", "info"))
.permitAll().matchers(EndpointRequest.toAnyEndpoint()) .permitAll().matchers(EndpointRequest.toAnyEndpoint())
.hasRole("ACTUATOR") .hasRole("ACTUATOR")
.matchers(StaticResourceRequest.toCommonLocations()).permitAll() .matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.pathMatchers("/login").permitAll().anyExchange().authenticated() .pathMatchers("/login").permitAll().anyExchange().authenticated()
.and().httpBasic(); .and().httpBasic();
return http.build(); return http.build();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment