Allow configuration of jee through nested builder

Issue: gh-5557
This commit is contained in:
Eleftheria Stein 2019-06-28 15:56:43 -04:00
parent 86f0f84740
commit bfc9538da1
2 changed files with 191 additions and 0 deletions

View File

@ -751,6 +751,86 @@ public final class HttpSecurity extends
return getOrApply(new JeeConfigurer<>());
}
/**
* Configures container based pre authentication. In this case, authentication
* is managed by the Servlet Container.
*
* <h2>Example Configuration</h2>
*
* The following configuration will use the principal found on the
* {@link HttpServletRequest} and if the user is in the role "ROLE_USER" or
* "ROLE_ADMIN" will add that to the resulting {@link Authentication}.
*
* <pre>
* &#064;Configuration
* &#064;EnableWebSecurity
* public class JeeSecurityConfig extends WebSecurityConfigurerAdapter {
*
* &#064;Override
* protected void configure(HttpSecurity http) throws Exception {
* http
* .authorizeRequests()
* .antMatchers(&quot;/**&quot;).hasRole(&quot;USER&quot;)
* .and()
* .jee(jee ->
* jee
* .mappableRoles(&quot;USER&quot;, &quot;ADMIN&quot;)
* );
* }
* }
* </pre>
*
* Developers wishing to use pre authentication with the container will need to ensure
* their web.xml configures the security constraints. For example, the web.xml (there
* is no equivalent Java based configuration supported by the Servlet specification)
* might look like:
*
* <pre>
* &lt;login-config&gt;
* &lt;auth-method&gt;FORM&lt;/auth-method&gt;
* &lt;form-login-config&gt;
* &lt;form-login-page&gt;/login&lt;/form-login-page&gt;
* &lt;form-error-page&gt;/login?error&lt;/form-error-page&gt;
* &lt;/form-login-config&gt;
* &lt;/login-config&gt;
*
* &lt;security-role&gt;
* &lt;role-name&gt;ROLE_USER&lt;/role-name&gt;
* &lt;/security-role&gt;
* &lt;security-constraint&gt;
* &lt;web-resource-collection&gt;
* &lt;web-resource-name&gt;Public&lt;/web-resource-name&gt;
* &lt;description&gt;Matches unconstrained pages&lt;/description&gt;
* &lt;url-pattern&gt;/login&lt;/url-pattern&gt;
* &lt;url-pattern&gt;/logout&lt;/url-pattern&gt;
* &lt;url-pattern&gt;/resources/*&lt;/url-pattern&gt;
* &lt;/web-resource-collection&gt;
* &lt;/security-constraint&gt;
* &lt;security-constraint&gt;
* &lt;web-resource-collection&gt;
* &lt;web-resource-name&gt;Secured Areas&lt;/web-resource-name&gt;
* &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
* &lt;/web-resource-collection&gt;
* &lt;auth-constraint&gt;
* &lt;role-name&gt;ROLE_USER&lt;/role-name&gt;
* &lt;/auth-constraint&gt;
* &lt;/security-constraint&gt;
* </pre>
*
* Last you will need to configure your container to contain the user with the correct
* roles. This configuration is specific to the Servlet Container, so consult your
* Servlet Container's documentation.
*
* @param jeeCustomizer the {@link Customizer} to provide more options for
* the {@link JeeConfigurer}
* @return the {@link HttpSecurity} for further customizations
* @throws Exception
*/
public HttpSecurity jee(Customizer<JeeConfigurer<HttpSecurity>> jeeCustomizer) throws Exception {
jeeCustomizer.customize(getOrApply(new JeeConfigurer<>()));
return HttpSecurity.this;
}
/**
* Configures X509 based pre authentication.
*

View File

@ -25,6 +25,9 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.test.SpringTestRule;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.preauth.j2ee.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource;
import org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthenticatedProcessingFilter;
import org.springframework.test.web.servlet.MockMvc;
@ -125,4 +128,112 @@ public class JeeConfigurerTests {
// @formatter:on
}
}
@Test
public void requestWhenJeeMappableRolesInLambdaThenAuthenticatedWithMappableRoles() throws Exception {
this.spring.register(JeeMappableRolesConfig.class).autowire();
Principal user = mock(Principal.class);
when(user.getName()).thenReturn("user");
this.mvc.perform(get("/")
.principal(user)
.with(request -> {
request.addUserRole("ROLE_ADMIN");
request.addUserRole("ROLE_USER");
return request;
}))
.andExpect(authenticated().withRoles("USER"));
}
@EnableWebSecurity
public static class JeeMappableRolesConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.jee(jee ->
jee
.mappableRoles("USER")
);
// @formatter:on
}
}
@Test
public void requestWhenJeeMappableAuthoritiesInLambdaThenAuthenticatedWithMappableAuthorities() throws Exception {
this.spring.register(JeeMappableAuthoritiesConfig.class).autowire();
Principal user = mock(Principal.class);
when(user.getName()).thenReturn("user");
this.mvc.perform(get("/")
.principal(user)
.with(request -> {
request.addUserRole("ROLE_ADMIN");
request.addUserRole("ROLE_USER");
return request;
}))
.andExpect(authenticated().withAuthorities(AuthorityUtils.createAuthorityList("ROLE_USER")));
}
@EnableWebSecurity
public static class JeeMappableAuthoritiesConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.jee(jee ->
jee
.mappableAuthorities("ROLE_USER")
);
// @formatter:on
}
}
@Test
public void requestWhenCustomAuthenticatedUserDetailsServiceInLambdaThenCustomAuthenticatedUserDetailsServiceUsed()
throws Exception {
this.spring.register(JeeCustomAuthenticatedUserDetailsServiceConfig.class).autowire();
Principal user = mock(Principal.class);
User userDetails = new User("user", "N/A", true, true, true, true,
AuthorityUtils.createAuthorityList("ROLE_USER"));
when(user.getName()).thenReturn("user");
when(JeeCustomAuthenticatedUserDetailsServiceConfig.authenticationUserDetailsService.loadUserDetails(any()))
.thenReturn(userDetails);
this.mvc.perform(get("/")
.principal(user)
.with(request -> {
request.addUserRole("ROLE_ADMIN");
request.addUserRole("ROLE_USER");
return request;
}))
.andExpect(authenticated().withRoles("USER"));
}
@EnableWebSecurity
public static class JeeCustomAuthenticatedUserDetailsServiceConfig extends WebSecurityConfigurerAdapter {
static AuthenticationUserDetailsService authenticationUserDetailsService =
mock(AuthenticationUserDetailsService.class);
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.jee(jee ->
jee
.authenticatedUserDetailsService(authenticationUserDetailsService)
);
// @formatter:on
}
}
}