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}
?
CodePudding user response:
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"));
}
}