From 3820f0f3a39e2539ccdf265e68d59d204725e219 Mon Sep 17 00:00:00 2001 From: sdratler1 Date: Mon, 12 Apr 2021 20:08:09 +0300 Subject: [PATCH] Add no-parameter authorizeHttpRequests method Closes gh-9498 --- .../annotation/web/builders/HttpSecurity.java | 82 ++++++++++++++++++- .../AuthorizeHttpRequestsConfigurerTests.java | 52 ++++++++++++ 2 files changed, 133 insertions(+), 1 deletion(-) diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java index ffc41987bf..6294f0e1b9 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java @@ -1320,7 +1320,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilderExample Configurations + * + * The most basic example is to configure all URLs to require the role "ROLE_USER". + * The configuration below requires authentication to every URL and will grant access + * to both the user "admin" and "user". + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class AuthorizeUrlsSecurityConfig extends WebSecurityConfigurerAdapter {
+	 *
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http
+	 *     .authorizeHttpRequests()
+	 *         .antMatchers("/**").hasRoles("USER")
+	 *         .and()
+	 *     .formLogin();
+	 * 	}
+	 * }
+	 * 
+ * + * We can also configure multiple URLs. The configuration below requires + * authentication to every URL and will grant access to URLs starting with /admin/ to + * only the "admin" user. All other URLs either user can access. + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class AuthorizeUrlsSecurityConfig extends WebSecurityConfigurerAdapter {
+	 *
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http
+	 *     .authorizeHttpRequests()
+	 *         .antMatchers("/**").hasRoles("USER")
+	 *         .and()
+	 *     .formLogin();
+	 * 			.formLogin(withDefaults());
+	 * 	}
+	 * }
+	 * 
+ * + * Note that the matchers are considered in order. Therefore, the following is invalid + * because the first matcher matches every request and will never get to the second + * mapping: + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class AuthorizeUrlsSecurityConfig extends WebSecurityConfigurerAdapter {
+	 *
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http
+	 *     .authorizeHttpRequests()
+	 *         .antMatchers("/**").hasRoles("USER")
+	 *         .and()
+	 *     .formLogin();
+	 * 	}
+	 * }
+	 * 
+ * @return the {@link HttpSecurity} for further customizations + * @throws Exception + * @since 5.5 + * @see #requestMatcher(RequestMatcher) + */ + public HttpSecurity authorizeHttpRequests() throws Exception { + ApplicationContext applicationContext = getContext(); + Customizer.AuthorizationManagerRequestMatcherRegistry> authorizeHttpRequestsCustomizer = Customizer + .withDefaults(); + authorizeHttpRequestsCustomizer + .customize(getOrApply(new AuthorizeHttpRequestsConfigurer<>(applicationContext)).getRegistry()); + return HttpSecurity.this; + } + /** * Allows configuring the Request Cache. For example, a protected page (/protected) * may be requested prior to authentication. The application will redirect the user to diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurerTests.java index 6e7a6ea7ca..6fabfee130 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurerTests.java @@ -72,6 +72,14 @@ public class AuthorizeHttpRequestsConfigurerTests { "At least one mapping is required (for example, authorizeHttpRequests().anyRequest().authenticated())"); } + @Test + public void configureWhenAuthorizedHttpRequestsAndNoRequestsThenExceptionWithDefaultConfig() { + assertThatExceptionOfType(BeanCreationException.class) + .isThrownBy(() -> this.spring.register(NoRequestsConfigWithDefaultConfig.class).autowire()) + .withMessageContaining( + "At least one mapping is required (for example, authorizeHttpRequests().anyRequest().authenticated())"); + } + @Test public void configureWhenAnyRequestIncompleteMappingThenException() { assertThatExceptionOfType(BeanCreationException.class) @@ -79,6 +87,14 @@ public class AuthorizeHttpRequestsConfigurerTests { .withMessageContaining("An incomplete mapping was found for "); } + @Test + public void configureWhenAnyRequestIncompleteMappingDefaultConfigThenException() { + assertThatExceptionOfType(BeanCreationException.class) + this.spring.register(IncompleteMappingConfigWithDefaultConfig.class, BasicController.class).autowire(); + this.mvc.perform(get("/")).andExpect(status().isOk()); + verify(CustomAuthorizationManagerConfig.authorizationManager).check(any(), any()); + } + @Test public void configureWhenMvcMatcherAfterAnyRequestThenException() { assertThatExceptionOfType(BeanCreationException.class) @@ -94,6 +110,14 @@ public class AuthorizeHttpRequestsConfigurerTests { verify(CustomAuthorizationManagerConfig.authorizationManager).check(any(), any()); } + @Test + public void configureMvcMatcherAccessAuthorizationManagerOnDefault() throws Exception { + CustomAuthorizationManagerConfig.authorizationManager = mock(AuthorizationManager.class); + this.spring.register(IncompleteMappingConfigWithDefaultConfig.class).autowire(); + this.mvc.perform(get("/")).andExpect(status().isUnauthorized()); + verify(CustomAuthorizationManagerConfig.authorizationManager).check(any(), any()); + } + @Test public void configureMvcMatcherAccessAuthorizationManagerWhenNullThenException() { CustomAuthorizationManagerConfig.authorizationManager = null; @@ -370,6 +394,34 @@ public class AuthorizeHttpRequestsConfigurerTests { } + @EnableWebSecurity + static class NoRequestsConfigWithDefaultConfig { + + @Bean + SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + // @formatter:off + return http + .authorizeHttpRequests() + .build(); + // @formatter:on + } + + } + + @EnableWebSecurity + static class IncompleteMappingConfigWithDefaultConfig { + + @Bean + FormLoginConfigurer filterChain(HttpSecurity http) throws Exception { + // @formatter:off + return http + .authorizeHttpRequests() + .formLogin(); + // @formatter:on + } + + } + @EnableWebSecurity static class IncompleteMappingConfig {