Skip to content

Commit

Permalink
Polish Servlet
Browse files Browse the repository at this point in the history
  • Loading branch information
jzheaux committed Jan 29, 2025
1 parent 1dbe3cf commit bcbbeb5
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1348,7 +1348,7 @@ SecurityFilterChain security(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeHttpRequests((authorize) -> authorize
.requestMatchers(mvc.pattern("/path/**")).hasRole("USER")
.requestMatchers(mvc.matcher("/path/**")).hasRole("USER")
)
.httpBasic(withDefaults());
// @formatter:on
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -596,8 +596,8 @@ import static org.springframework.security.web.servlet.util.matcher.ServletReque
SecurityFilterChain appEndpoints(HttpSecurity http) {
http
.authorizeHttpRequests((authorize) -> authorize
.requestMatchers(servletPath("/spring-mvc").pattern("/admin/**")).hasAuthority("admin")
.requestMatchers(servletPath("/spring-mvc").pattern("/my/controller/**")).hasAuthority("controller")
.requestMatchers(servletPath("/spring-mvc").matcher("/admin/**")).hasAuthority("admin")
.requestMatchers(servletPath("/spring-mvc").matcher("/my/controller/**")).hasAuthority("controller")
.anyRequest().authenticated()
);
Expand Down Expand Up @@ -646,8 +646,8 @@ SecurityFilterChain appEndpoints(HttpSecurity http) {
RequestMatcherBuilder mvc = servletPath("/spring-mvc");
http
.authorizeHttpRequests((authorize) -> authorize
.requestMatchers(mvc.pattern("/admin/**")).hasAuthority("admin")
.requestMatchers(mvc.pattern("/my/controller/**")).hasAuthority("controller")
.requestMatchers(mvc.matcher("/admin/**")).hasAuthority("admin")
.requestMatchers(mvc.matcher("/my/controller/**")).hasAuthority("controller")
.anyRequest().authenticated()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.MappingMatch;

import org.springframework.http.HttpMethod;
import org.springframework.lang.Nullable;
import org.springframework.security.web.util.matcher.AndRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
Expand Down Expand Up @@ -90,14 +91,23 @@ public static RequestMatcherBuilder servletPath(String servletPath) {
Assert.isTrue(servletPath.startsWith("/"), "servletPath must start with '/'");
Assert.isTrue(!servletPath.endsWith("/"), "servletPath must not end with a slash");
Assert.isTrue(!servletPath.contains("*"), "servletPath must not contain a star");
RequestMatcher servletPathMatcher = new ServletPathRequestMatcher(servletPath);
return (method, pattern) -> {
return new ServletRequestMatcherBuilder(servletPath);
}

private record ServletRequestMatcherBuilder(String servletPath) implements RequestMatcherBuilder {
@Override
public RequestMatcher anyRequest() {
return new ServletPathRequestMatcher(this.servletPath);
}

@Override
public RequestMatcher matcher(HttpMethod method, String pattern) {
Assert.notNull(pattern, "pattern cannot be null");
Assert.isTrue(pattern.startsWith("/"), "pattern must start with '/'");
PathPatternRequestMatcher pathPattern = PathPatternRequestMatcher.pathPattern(method,
servletPath + pattern);
return new AndRequestMatcher(servletPathMatcher, pathPattern);
};
this.servletPath + pattern);
return new AndRequestMatcher(new ServletPathRequestMatcher(this.servletPath), pathPattern);
}
}

private record ServletPathRequestMatcher(String path) implements RequestMatcher {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,25 @@
class ServletRequestMatcherBuildersTests {

@Test
void patternWhenServletPathThenMatchesOnlyServletPath() {
void matcherWhenServletPathThenMatchesOnlyServletPath() {
RequestMatcherBuilder builder = ServletRequestMatcherBuilders.servletPath("/servlet/path");
RequestMatcher requestMatcher = builder.pattern(HttpMethod.GET, "/endpoint");
RequestMatcher requestMatcher = builder.matcher(HttpMethod.GET, "/endpoint");
assertThat(requestMatcher.matches(request("/servlet/path/endpoint", "/servlet/path"))).isTrue();
assertThat(requestMatcher.matches(request("/endpoint", "/endpoint", "/servlet/path/*"))).isFalse();
}

@Test
void patternWhenRequestPathThenIgnoresServletPath() {
void matcherWhenRequestPathThenIgnoresServletPath() {
RequestMatcherBuilder builder = ServletRequestMatcherBuilders.requestPath();
RequestMatcher requestMatcher = builder.pattern(HttpMethod.GET, "/endpoint");
RequestMatcher requestMatcher = builder.matcher(HttpMethod.GET, "/endpoint");
assertThat(requestMatcher.matches(request("/servlet/path/endpoint", "/servlet/path", "/endpoint"))).isFalse();
assertThat(requestMatcher.matches(request("/endpoint", "/endpoint"))).isTrue();
}

@Test
void patternWhenServletPathThenRequiresServletPathToExist() {
void matcherWhenServletPathThenRequiresServletPathToExist() {
RequestMatcherBuilder builder = ServletRequestMatcherBuilders.servletPath("/servlet/path");
RequestMatcher requestMatcher = builder.pattern(HttpMethod.GET, "/endpoint");
RequestMatcher requestMatcher = builder.matcher(HttpMethod.GET, "/endpoint");
assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(() -> requestMatcher.matches(request("/servlet/path/endpoint", "/servlet/path", "")));
}
Expand Down

0 comments on commit bcbbeb5

Please sign in to comment.