I have several different controllers, configured with endpoints like below. Where {id}
is a numeric @PathVariable
.
@RequestMapping(value = "/noun1/noun2/{id}/verb1") @RequestMapping(value = "/noun1/noun2/{id}/verb2") @RequestMapping(value = "/noun1/noun2/{id}/verb3/verb4") @RequestMapping(value = "/noun1/noun2/noun3/verb5")
Using HttpSecurity
, I want to implement security around all endpoints that have {id}
in them. So I created an ant pattern like this:
"/noun1/noun2/{id}/**"
The ant pattern is correctly matching on the endpoints with {id}
in them. However, the ant pattern is also matching on the last endpoint, setting id = noun3
. Is there a way with ant patterns to only match the endpoints containing {id}
?
Advertisement
Answer
How your ant pattern should be depends on what {id}
can be. The {id}
in your ant matcher is not directly related to your {id}
in your RequestMapping
annotation.
Spring Security just checks, with the ant matcher, whether the path matches the provided pattern. In your case {id}
matches any string and stores the matched value in a URI template variable
named id
for later use.
To specify the what is considered an {id}
you can provide an regex. If your id consists of digits your matcher could be "/noun1/noun2/{regex:\d+}/**"
:
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.springframework.util.AntPathMatcher; class AntMatcherTest { @Test void antMatcher() { AntPathMatcher antPathMatcher = new AntPathMatcher(); String pattern = "/noun1/noun2/{id:\d+}/**"; assertFalse(antPathMatcher.match(pattern, "/noun1/noun2/noun3/verb5")); assertTrue(antPathMatcher.match(pattern, "/noun1/noun2/1/verb1")); assertTrue(antPathMatcher.match(pattern, "/noun1/noun2/2/verb2")); assertTrue(antPathMatcher.match(pattern, "/noun1/noun2/3/verb3/verb4")); } }