From 1ad9f15e193b9967ea6a83033514b64be59a7967 Mon Sep 17 00:00:00 2001 From: Eleftheria Stein Date: Thu, 4 Jul 2019 16:55:38 -0400 Subject: [PATCH] Allow configuration of requires channel through nested builder Issue: gh-5557 --- .../annotation/web/builders/HttpSecurity.java | 53 +++++++++++++++++-- .../ChannelSecurityConfigurerTests.java | 23 ++++++++ .../PortMapperConfigurerTests.java | 14 ++--- 3 files changed, 81 insertions(+), 9 deletions(-) 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 db0f24bede..c609fa6056 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 @@ -658,9 +658,10 @@ public final class HttpSecurity extends * @Override * protected void configure(HttpSecurity http) throws Exception { * http - * .requiresChannel() - * .anyRequest().requiresSecure() - * .and() + * .requiresChannel(requiresChannel -> + * requiresChannel + * .anyRequest().requiresSecure() + * ) * .portMapper(portMapper -> * portMapper * .http(9090).mapsTo(9443) @@ -1894,6 +1895,52 @@ public final class HttpSecurity extends .getRegistry(); } + /** + * Configures channel security. In order for this configuration to be useful at least + * one mapping to a required channel must be provided. + * + *

Example Configuration

+ * + * The example below demonstrates how to require HTTPs for every request. Only + * requiring HTTPS for some requests is supported, but not recommended since an + * application that allows for HTTP introduces many security vulnerabilities. For one + * such example, read about Firesheep. + * + *
+	 * @Configuration
+	 * @EnableWebSecurity
+	 * public class ChannelSecurityConfig extends WebSecurityConfigurerAdapter {
+	 *
+	 * 	@Override
+	 * 	protected void configure(HttpSecurity http) throws Exception {
+	 * 		http
+	 * 			.authorizeRequests(authorizeRequests ->
+	 * 				authorizeRequests
+	 * 					.antMatchers("/**").hasRole("USER")
+	 * 			)
+	 * 			.formLogin(withDefaults())
+	 * 			.requiresChannel(requiresChannel ->
+	 * 				requiresChannel
+	 * 					.anyRequest().requiresSecure()
+	 * 			);
+	 * 	}
+	 * }
+	 * 
+ * + * @param requiresChannelCustomizer the {@link Customizer} to provide more options for + * the {@link ChannelSecurityConfigurer.ChannelRequestMatcherRegistry} + * @return the {@link HttpSecurity} for further customizations + * @throws Exception + */ + public HttpSecurity requiresChannel(Customizer.ChannelRequestMatcherRegistry> requiresChannelCustomizer) + throws Exception { + ApplicationContext context = getContext(); + requiresChannelCustomizer.customize(getOrApply(new ChannelSecurityConfigurer<>(context)) + .getRegistry()); + return HttpSecurity.this; + } + /** * Configures HTTP Basic authentication. * diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.java index c755c5f3a3..c33682e716 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.java @@ -135,4 +135,27 @@ public class ChannelSecurityConfigurerTests { // @formatter:on } } + + @Test + public void requestWhenRequiresChannelConfiguredInLambdaThenRedirectsToHttps() throws Exception { + this.spring.register(RequiresChannelInLambdaConfig.class).autowire(); + + mvc.perform(get("/")) + .andExpect(redirectedUrl("https://localhost/")); + } + + @EnableWebSecurity + static class RequiresChannelInLambdaConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http + .requiresChannel(requiresChannel -> + requiresChannel + .anyRequest().requiresSecure() + ); + // @formatter:on + } + } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java index d9ed42ff22..bd68d2ecec 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -79,9 +79,10 @@ public class PortMapperConfigurerTests { protected void configure(HttpSecurity http) throws Exception { // @formatter:off http - .requiresChannel() + .requiresChannel(requiresChannel -> + requiresChannel .anyRequest().requiresSecure() - .and() + ) .portMapper(portMapper -> portMapper .http(543).mapsTo(123) @@ -106,9 +107,10 @@ public class PortMapperConfigurerTests { customPortMapper.setPortMappings(Collections.singletonMap("543", "123")); // @formatter:off http - .requiresChannel() - .anyRequest().requiresSecure() - .and() + .requiresChannel(requiresChannel -> + requiresChannel + .anyRequest().requiresSecure() + ) .portMapper(portMapper -> portMapper .portMapper(customPortMapper)