NamespaceHttpTests groovy->java

Issue: gh-4939
This commit is contained in:
Joe Grandja
2018-02-16 15:40:58 -05:00
parent c24490cbb8
commit dc9248e73c
3 changed files with 582 additions and 533 deletions

View File

@@ -0,0 +1,582 @@
/*
* Copyright 2002-2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.config.annotation.web.builders;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.jaas.JaasAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.UrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.config.test.SpringTestRule;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.PasswordEncodedUser;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.context.NullSecurityContextRepository;
import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.stereotype.Controller;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.web.bind.annotation.GetMapping;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
/**
* Tests to verify that all the functionality of <http> attributes are present in Java Config.
*
* @author Rob Winch
* @author Joe Grandja
*/
public class NamespaceHttpTests {
@Rule
public final SpringTestRule spring = new SpringTestRule();
@Autowired
private MockMvc mockMvc;
@Test // http@access-decision-manager-ref
public void configureWhenAccessDecisionManagerSetThenVerifyUse() throws Exception {
AccessDecisionManagerRefConfig.ACCESS_DECISION_MANAGER = mock(AccessDecisionManager.class);
when(AccessDecisionManagerRefConfig.ACCESS_DECISION_MANAGER.supports(FilterInvocation.class)).thenReturn(true);
when(AccessDecisionManagerRefConfig.ACCESS_DECISION_MANAGER.supports(any(ConfigAttribute.class))).thenReturn(true);
this.spring.register(AccessDecisionManagerRefConfig.class).autowire();
this.mockMvc.perform(get("/"));
verify(AccessDecisionManagerRefConfig.ACCESS_DECISION_MANAGER, times(1)).decide(any(Authentication.class), any(), anyCollection());
}
@EnableWebSecurity
static class AccessDecisionManagerRefConfig extends WebSecurityConfigurerAdapter {
static AccessDecisionManager ACCESS_DECISION_MANAGER;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().permitAll()
.accessDecisionManager(ACCESS_DECISION_MANAGER);
}
}
@Test // http@access-denied-page
public void configureWhenAccessDeniedPageSetAndRequestForbiddenThenForwardedToAccessDeniedPage() throws Exception {
this.spring.register(AccessDeniedPageConfig.class).autowire();
this.mockMvc.perform(get("/admin").with(user(PasswordEncodedUser.user())))
.andExpect(status().isForbidden())
.andExpect(forwardedUrl("/AccessDeniedPage"));
}
@EnableWebSecurity
static class AccessDeniedPageConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.exceptionHandling()
.accessDeniedPage("/AccessDeniedPage");
}
}
@Test // http@authentication-manager-ref
public void configureWhenAuthenticationManagerProvidedThenVerifyUse() throws Exception {
AuthenticationManagerRefConfig.AUTHENTICATION_MANAGER = mock(AuthenticationManager.class);
this.spring.register(AuthenticationManagerRefConfig.class).autowire();
this.mockMvc.perform(formLogin());
verify(AuthenticationManagerRefConfig.AUTHENTICATION_MANAGER, times(1)).authenticate(any(Authentication.class));
}
@EnableWebSecurity
static class AuthenticationManagerRefConfig extends WebSecurityConfigurerAdapter {
static AuthenticationManager AUTHENTICATION_MANAGER;
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return AUTHENTICATION_MANAGER;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin();
}
}
@Test // http@create-session=always
public void configureWhenSessionCreationPolicyAlwaysThenSessionCreatedOnRequest() throws Exception {
this.spring.register(CreateSessionAlwaysConfig.class).autowire();
MvcResult mvcResult = this.mockMvc.perform(get("/")).andReturn();
HttpSession session = mvcResult.getRequest().getSession(false);
assertThat(session).isNotNull();
assertThat(session.isNew()).isTrue();
}
@EnableWebSecurity
static class CreateSessionAlwaysConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().permitAll()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
}
}
@Test // http@create-session=stateless
public void configureWhenSessionCreationPolicyStatelessThenSessionNotCreatedOnRequest() throws Exception {
this.spring.register(CreateSessionStatelessConfig.class).autowire();
MvcResult mvcResult = this.mockMvc.perform(get("/")).andReturn();
HttpSession session = mvcResult.getRequest().getSession(false);
assertThat(session).isNull();
}
@EnableWebSecurity
static class CreateSessionStatelessConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().permitAll()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
@Test // http@create-session=ifRequired
public void configureWhenSessionCreationPolicyIfRequiredThenSessionCreatedWhenRequiredOnRequest() throws Exception {
this.spring.register(IfRequiredConfig.class).autowire();
MvcResult mvcResult = this.mockMvc.perform(get("/unsecure")).andReturn();
HttpSession session = mvcResult.getRequest().getSession(false);
assertThat(session).isNull();
mvcResult = this.mockMvc.perform(formLogin()).andReturn();
session = mvcResult.getRequest().getSession(false);
assertThat(session).isNotNull();
assertThat(session.isNew()).isTrue();
}
@EnableWebSecurity
static class IfRequiredConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/unsecure").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.formLogin();
}
}
@Test // http@create-session=never
public void configureWhenSessionCreationPolicyNeverThenSessionNotCreatedOnRequest() throws Exception {
this.spring.register(CreateSessionNeverConfig.class).autowire();
MvcResult mvcResult = this.mockMvc.perform(get("/")).andReturn();
HttpSession session = mvcResult.getRequest().getSession(false);
assertThat(session).isNull();
}
@EnableWebSecurity
static class CreateSessionNeverConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().anonymous()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.NEVER);
}
}
@Test // http@entry-point-ref
public void configureWhenAuthenticationEntryPointSetAndRequestUnauthorizedThenRedirectedToAuthenticationEntryPoint() throws Exception {
this.spring.register(EntryPointRefConfig.class).autowire();
this.mockMvc.perform(get("/"))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrlPattern("**/entry-point"));
}
@EnableWebSecurity
static class EntryPointRefConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/entry-point"))
.and()
.formLogin();
}
}
@Test // http@jaas-api-provision
public void configureWhenJaasApiIntegrationFilterAddedThenJaasSubjectObtained() throws Exception {
LoginContext loginContext = mock(LoginContext.class);
when(loginContext.getSubject()).thenReturn(new Subject());
JaasAuthenticationToken authenticationToken = mock(JaasAuthenticationToken.class);
when(authenticationToken.isAuthenticated()).thenReturn(true);
when(authenticationToken.getLoginContext()).thenReturn(loginContext);
this.spring.register(JaasApiProvisionConfig.class).autowire();
this.mockMvc.perform(get("/").with(authentication(authenticationToken)));
verify(loginContext, times(1)).getSubject();
}
@EnableWebSecurity
static class JaasApiProvisionConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilter(new JaasApiIntegrationFilter());
}
}
@Test // http@realm
public void configureWhenHttpBasicAndRequestUnauthorizedThenReturnWWWAuthenticateWithRealm() throws Exception {
this.spring.register(RealmConfig.class).autowire();
this.mockMvc.perform(get("/"))
.andExpect(status().isUnauthorized())
.andExpect(header().string("WWW-Authenticate", "Basic realm=\"RealmConfig\""));
}
@EnableWebSecurity
static class RealmConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic()
.realmName("RealmConfig");
}
}
@Test // http@request-matcher-ref ant
public void configureWhenAntPatternMatchingThenAntPathRequestMatcherUsed() throws Exception {
this.spring.register(RequestMatcherAntConfig.class).autowire();
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(0);
assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
}
@EnableWebSecurity
static class RequestMatcherAntConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**");
}
}
@Test // http@request-matcher-ref regex
public void configureWhenRegexPatternMatchingThenRegexRequestMatcherUsed() throws Exception {
this.spring.register(RequestMatcherRegexConfig.class).autowire();
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(0);
assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(RegexRequestMatcher.class);
}
@EnableWebSecurity
static class RequestMatcherRegexConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.regexMatcher("/regex/.*");
}
}
@Test // http@request-matcher-ref
public void configureWhenRequestMatcherProvidedThenRequestMatcherUsed() throws Exception {
this.spring.register(RequestMatcherRefConfig.class).autowire();
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(0);
assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(RequestMatcherRefConfig.MyRequestMatcher.class);
}
@EnableWebSecurity
static class RequestMatcherRefConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatcher(new MyRequestMatcher());
}
static class MyRequestMatcher implements RequestMatcher {
public boolean matches(HttpServletRequest request) {
return true;
}
}
}
@Test // http@security=none
public void configureWhenIgnoredAntPatternsThenAntPathRequestMatcherUsedWithNoFilters() throws Exception {
this.spring.register(SecurityNoneConfig.class).autowire();
FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
assertThat(filterChainProxy.getFilterChains().get(0)).isInstanceOf(DefaultSecurityFilterChain.class);
DefaultSecurityFilterChain securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(0);
assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern()).isEqualTo("/resources/**");
assertThat(securityFilterChain.getFilters()).isEmpty();
assertThat(filterChainProxy.getFilterChains().get(1)).isInstanceOf(DefaultSecurityFilterChain.class);
securityFilterChain = (DefaultSecurityFilterChain) filterChainProxy.getFilterChains().get(1);
assertThat(securityFilterChain.getRequestMatcher()).isInstanceOf(AntPathRequestMatcher.class);
assertThat(((AntPathRequestMatcher) securityFilterChain.getRequestMatcher()).getPattern()).isEqualTo("/public/**");
assertThat(securityFilterChain.getFilters()).isEmpty();
}
@EnableWebSecurity
static class SecurityNoneConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**", "/public/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
}
}
@Test // http@security-context-repository-ref
public void configureWhenNullSecurityContextRepositoryThenSecurityContextNotSavedInSession() throws Exception {
this.spring.register(SecurityContextRepoConfig.class).autowire();
MvcResult mvcResult = this.mockMvc.perform(formLogin()).andReturn();
HttpSession session = mvcResult.getRequest().getSession(false);
assertThat(session).isNull();
}
@EnableWebSecurity
static class SecurityContextRepoConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.securityContext()
.securityContextRepository(new NullSecurityContextRepository())
.and()
.formLogin();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser(PasswordEncodedUser.user());
}
}
@Test // http@servlet-api-provision=false
public void configureWhenServletApiDisabledThenRequestNotServletApiWrapper() throws Exception {
this.spring.register(ServletApiProvisionConfig.class, MainController.class).autowire();
this.mockMvc.perform(get("/"));
assertThat(MainController.HTTP_SERVLET_REQUEST_TYPE).isNotInstanceOf(SecurityContextHolderAwareRequestWrapper.class);
}
@EnableWebSecurity
static class ServletApiProvisionConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().permitAll()
.and()
.servletApi()
.disable();
}
}
@Test // http@servlet-api-provision defaults to true
public void configureWhenServletApiDefaultThenRequestIsServletApiWrapper() throws Exception {
this.spring.register(ServletApiProvisionDefaultsConfig.class, MainController.class).autowire();
this.mockMvc.perform(get("/"));
assertThat(SecurityContextHolderAwareRequestWrapper.class).isAssignableFrom(MainController.HTTP_SERVLET_REQUEST_TYPE);
}
@EnableWebSecurity
static class ServletApiProvisionDefaultsConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().permitAll();
}
}
@Controller
static class MainController {
static Class<? extends HttpServletRequest> HTTP_SERVLET_REQUEST_TYPE;
@GetMapping("/")
public String index(HttpServletRequest request) {
HTTP_SERVLET_REQUEST_TYPE = request.getClass();
return "index";
}
}
@Test // http@use-expressions=true
public void configureWhenUseExpressionsEnabledThenExpressionBasedSecurityMetadataSource() throws Exception {
this.spring.register(UseExpressionsConfig.class).autowire();
UseExpressionsConfig config = this.spring.getContext().getBean(UseExpressionsConfig.class);
assertThat(ExpressionBasedFilterInvocationSecurityMetadataSource.class)
.isAssignableFrom(config.filterInvocationSecurityMetadataSourceType);
}
@EnableWebSecurity
static class UseExpressionsConfig extends WebSecurityConfigurerAdapter {
private Class<? extends FilterInvocationSecurityMetadataSource> filterInvocationSecurityMetadataSourceType;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/users**", "/sessions/**").hasRole("USER")
.antMatchers("/signup").permitAll()
.anyRequest().hasRole("USER");
}
@Override
public void init(final WebSecurity web) throws Exception {
super.init(web);
final HttpSecurity http = this.getHttp();
web.postBuildAction(() -> {
FilterSecurityInterceptor securityInterceptor = http.getSharedObject(FilterSecurityInterceptor.class);
UseExpressionsConfig.this.filterInvocationSecurityMetadataSourceType =
securityInterceptor.getSecurityMetadataSource().getClass();
});
}
}
@Test // http@use-expressions=false
public void configureWhenUseExpressionsDisabledThenDefaultSecurityMetadataSource() throws Exception {
this.spring.register(DisableUseExpressionsConfig.class).autowire();
DisableUseExpressionsConfig config = this.spring.getContext().getBean(DisableUseExpressionsConfig.class);
assertThat(DefaultFilterInvocationSecurityMetadataSource.class)
.isAssignableFrom(config.filterInvocationSecurityMetadataSourceType);
}
@EnableWebSecurity
static class DisableUseExpressionsConfig extends WebSecurityConfigurerAdapter {
private Class<? extends FilterInvocationSecurityMetadataSource> filterInvocationSecurityMetadataSourceType;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.apply(new UrlAuthorizationConfigurer<>(getApplicationContext())).getRegistry()
.antMatchers("/users**", "/sessions/**").hasRole("USER")
.antMatchers("/signup").hasRole("ANONYMOUS")
.anyRequest().hasRole("USER");
}
@Override
public void init(final WebSecurity web) throws Exception {
super.init(web);
final HttpSecurity http = this.getHttp();
web.postBuildAction(() -> {
FilterSecurityInterceptor securityInterceptor = http.getSharedObject(FilterSecurityInterceptor.class);
DisableUseExpressionsConfig.this.filterInvocationSecurityMetadataSourceType =
securityInterceptor.getSecurityMetadataSource().getClass();
});
}
}
}