Allow configuration of requires channel through nested builder

Issue: gh-5557
This commit is contained in:
Eleftheria Stein 2019-07-04 16:55:38 -04:00
parent ae8e12f049
commit 1ad9f15e19
3 changed files with 81 additions and 9 deletions

View File

@ -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.
*
* <h2>Example Configuration</h2>
*
* 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 <a
* href="https://en.wikipedia.org/wiki/Firesheep">Firesheep</a>.
*
* <pre>
* &#064;Configuration
* &#064;EnableWebSecurity
* public class ChannelSecurityConfig extends WebSecurityConfigurerAdapter {
*
* &#064;Override
* protected void configure(HttpSecurity http) throws Exception {
* http
* .authorizeRequests(authorizeRequests ->
* authorizeRequests
* .antMatchers(&quot;/**&quot;).hasRole(&quot;USER&quot;)
* )
* .formLogin(withDefaults())
* .requiresChannel(requiresChannel ->
* requiresChannel
* .anyRequest().requiresSecure()
* );
* }
* }
* </pre>
*
* @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<ChannelSecurityConfigurer<HttpSecurity>.ChannelRequestMatcherRegistry> requiresChannelCustomizer)
throws Exception {
ApplicationContext context = getContext();
requiresChannelCustomizer.customize(getOrApply(new ChannelSecurityConfigurer<>(context))
.getRegistry());
return HttpSecurity.this;
}
/**
* Configures HTTP Basic authentication.
*

View File

@ -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
}
}
}

View File

@ -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)