Simplify Java Configuration RequestMatcher Usage
If Spring MVC is present in the classpath, use MvcRequestMatcher by default. This commit also adds a new securityMatcher method in HttpSecurity Closes gh-11347 Closes gh-9159
This commit is contained in:
committed by
Marcus Hert Da Coregio
parent
bf59d7c374
commit
039e0328e1
@@ -109,13 +109,14 @@ SecurityFilterChain web(HttpSecurity http, AuthorizationManager<RequestAuthoriza
|
||||
|
||||
@Bean
|
||||
AuthorizationManager<RequestAuthorizationContext> requestMatcherAuthorizationManager(HandlerMappingIntrospector introspector) {
|
||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector);
|
||||
RequestMatcher permitAll =
|
||||
new AndRequestMatcher(
|
||||
new MvcRequestMatcher(introspector, "/resources/**"),
|
||||
new MvcRequestMatcher(introspector, "/signup"),
|
||||
new MvcRequestMatcher(introspector, "/about"));
|
||||
RequestMatcher admin = new MvcRequestMatcher(introspector, "/admin/**");
|
||||
RequestMatcher db = new MvcRequestMatcher(introspector, "/db/**");
|
||||
mvcMatcherBuilder.pattern("/resources/**"),
|
||||
mvcMatcherBuilder.pattern("/signup"),
|
||||
mvcMatcherBuilder.pattern("/about"));
|
||||
RequestMatcher admin = mvcMatcherBuilder.pattern("/admin/**");
|
||||
RequestMatcher db = mvcMatcherBuilder.pattern("/db/**");
|
||||
RequestMatcher any = AnyRequestMatcher.INSTANCE;
|
||||
AuthorizationManager<HttpRequestServlet> manager = RequestMatcherDelegatingAuthorizationManager.builder()
|
||||
.add(permitAll, (context) -> new AuthorizationDecision(true))
|
||||
|
||||
@@ -145,7 +145,7 @@ You could refer to the method using:
|
||||
----
|
||||
http
|
||||
.authorizeHttpRequests(authorize -> authorize
|
||||
.antMatchers("/user/**").access("@webSecurity.check(authentication,request)")
|
||||
.requestMatchers("/user/**").access("@webSecurity.check(authentication,request)")
|
||||
...
|
||||
)
|
||||
----
|
||||
@@ -211,7 +211,7 @@ You could refer to the method using:
|
||||
----
|
||||
http
|
||||
.authorizeHttpRequests(authorize -> authorize
|
||||
.antMatchers("/user/{userId}/**").access("@webSecurity.checkUserId(authentication,#userId)")
|
||||
.requestMatchers("/user/{userId}/**").access("@webSecurity.checkUserId(authentication,#userId)")
|
||||
...
|
||||
);
|
||||
----
|
||||
|
||||
@@ -139,8 +139,8 @@ If we wanted to restrict access to this controller method to admin users, a deve
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeHttpRequests(authorize -> authorize
|
||||
.antMatchers("/admin").hasRole("ADMIN")
|
||||
.authorizeHttpRequests((authorize) -> authorize
|
||||
.requestMatchers("/admin").hasRole("ADMIN")
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
@@ -152,8 +152,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
@Bean
|
||||
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
http {
|
||||
authorizeRequests {
|
||||
authorize(AntPathRequestMatcher("/admin"), hasRole("ADMIN"))
|
||||
authorizeHttpRequests {
|
||||
authorize("/admin", hasRole("ADMIN"))
|
||||
}
|
||||
}
|
||||
return http.build()
|
||||
@@ -177,21 +177,24 @@ Additionally, depending on our Spring MVC configuration, the URL `/admin/` will
|
||||
The problem is that our security rule is only protecting `/admin`.
|
||||
We could add additional rules for all the permutations of Spring MVC, but this would be quite verbose and tedious.
|
||||
|
||||
Instead, we can leverage Spring Security's `MvcRequestMatcher`.
|
||||
The following configuration will protect the same URLs that Spring MVC will match on by using Spring MVC to match on the URL.
|
||||
Fortunately, when using the `requestMatchers` DSL method, Spring Security automatically creates a `MvcRequestMatcher` if it detects that Spring MVC is available in the classpath.
|
||||
Therefore, it will protect the same URLs that Spring MVC will match on by using Spring MVC to match on the URL.
|
||||
|
||||
One common requirement when using Spring MVC is to specify the servlet path property, for that you can use the `MvcRequestMatcher.Builder` to create multiple `MvcRequestMatcher` instances that share the same servlet path:
|
||||
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
public SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
|
||||
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector).servletPath("/path");
|
||||
http
|
||||
.authorizeHttpRequests(authorize -> authorize
|
||||
.mvcMatchers("/admin").hasRole("ADMIN")
|
||||
.authorizeHttpRequests((authorize) -> authorize
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/admin")).hasRole("ADMIN")
|
||||
.requestMatchers(mvcMatcherBuilder.pattern("/user")).hasRole("USER")
|
||||
);
|
||||
// ...
|
||||
return http.build();
|
||||
}
|
||||
----
|
||||
|
||||
@@ -199,25 +202,19 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
[source,kotlin,role="secondary"]
|
||||
----
|
||||
@Bean
|
||||
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
open fun filterChain(http: HttpSecurity, introspector: HandlerMappingIntrospector): SecurityFilterChain {
|
||||
val mvcMatcherBuilder = MvcRequestMatcher.Builder(introspector)
|
||||
http {
|
||||
authorizeRequests {
|
||||
authorize("/admin", hasRole("ADMIN"))
|
||||
authorizeHttpRequests {
|
||||
authorize(mvcMatcherBuilder.pattern("/admin"), hasRole("ADMIN"))
|
||||
authorize(mvcMatcherBuilder.pattern("/user"), hasRole("USER"))
|
||||
}
|
||||
}
|
||||
// ...
|
||||
return http.build()
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
or in XML
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<http request-matcher="mvc">
|
||||
<intercept-url pattern="/admin" access="hasRole('ADMIN')"/>
|
||||
</http>
|
||||
----
|
||||
|
||||
[[mvc-authentication-principal]]
|
||||
== @AuthenticationPrincipal
|
||||
|
||||
@@ -567,7 +567,7 @@ public class WebSecurityConfig {
|
||||
http
|
||||
.csrf(csrf -> csrf
|
||||
// ignore our stomp endpoints since they are protected using Stomp headers
|
||||
.ignoringAntMatchers("/chat/**")
|
||||
.ignoringRequestMatchers("/chat/**")
|
||||
)
|
||||
.headers(headers -> headers
|
||||
// allow same origin to frame our site to support iframe SockJS
|
||||
@@ -591,7 +591,7 @@ open class WebSecurityConfig {
|
||||
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
|
||||
http {
|
||||
csrf {
|
||||
ignoringAntMatchers("/chat/**")
|
||||
ignoringRequestMatchers("/chat/**")
|
||||
}
|
||||
headers {
|
||||
frameOptions {
|
||||
|
||||
@@ -11,3 +11,5 @@ Below are the highlights of the release.
|
||||
* https://github.com/spring-projects/spring-security/pull/11232[gh-11232] - `ClientRegistrations#rest` defines 30s connect and read timeouts
|
||||
* https://github.com/spring-projects/spring-security/pull/11464[gh-11464] - Remember Me supports SHA256 algorithm
|
||||
* https://github.com/spring-projects/spring-security/pull/11908[gh-11908] - Make X-Xss-Protection header value configurable in ServerHttpSecurity
|
||||
* https://github.com/spring-projects/spring-security/issues/11347[gh-11347] - Simplify Java Configuration `RequestMatcher` Usage
|
||||
* https://github.com/spring-projects/spring-security/issues/9159[gh-9159] - Add `securityMatcher` as an alias on `requestMatcher` in `HttpSecurity`
|
||||
|
||||
Reference in New Issue
Block a user