diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java b/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java index d2cea903a4..11d2b4e6cb 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java @@ -54,7 +54,7 @@ public abstract class AbstractRequestMatcherRegistry { private ApplicationContext context; - private boolean anyRequestConfigured = false; + protected boolean anyRequestConfigured = false; protected final void setApplicationContext(ApplicationContext context) { this.context = context; @@ -165,7 +165,8 @@ public abstract class AbstractRequestMatcherRegistry { if (!this.context.containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) { throw new NoSuchBeanDefinitionException("A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME + " of type " + HandlerMappingIntrospector.class.getName() - + " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext."); + + " is required to use MvcRequestMatcher." + + " Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext."); } HandlerMappingIntrospector introspector = this.context.getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME, HandlerMappingIntrospector.class); @@ -265,7 +266,7 @@ public abstract class AbstractRequestMatcherRegistry { * @author Rob Winch * @since 3.2 */ - private static final class RequestMatchers { + public static final class RequestMatchers { private RequestMatchers() { } @@ -278,7 +279,7 @@ public abstract class AbstractRequestMatcherRegistry { * from * @return a {@link List} of {@link AntPathRequestMatcher} instances */ - static List antMatchers(HttpMethod httpMethod, String... antPatterns) { + public static List antMatchers(HttpMethod httpMethod, String... antPatterns) { String method = (httpMethod != null) ? httpMethod.toString() : null; List matchers = new ArrayList<>(); for (String pattern : antPatterns) { @@ -294,7 +295,7 @@ public abstract class AbstractRequestMatcherRegistry { * from * @return a {@link List} of {@link AntPathRequestMatcher} instances */ - static List antMatchers(String... antPatterns) { + public static List antMatchers(String... antPatterns) { return antMatchers(null, antPatterns); } diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java index c4934cb862..b7c18234b2 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java @@ -17,6 +17,7 @@ package org.springframework.security.config.annotation.web.builders; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import javax.servlet.Filter; @@ -30,6 +31,7 @@ import org.springframework.beans.BeansException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; +import org.springframework.core.log.LogMessage; import org.springframework.http.HttpMethod; import org.springframework.security.access.PermissionEvaluator; import org.springframework.security.access.expression.SecurityExpressionHandler; @@ -60,6 +62,7 @@ import org.springframework.security.web.debug.DebugFilter; import org.springframework.security.web.firewall.HttpFirewall; import org.springframework.security.web.firewall.RequestRejectedHandler; import org.springframework.security.web.firewall.StrictHttpFirewall; +import org.springframework.security.web.server.restriction.IgnoreRequestMatcher; import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcherEntry; @@ -108,7 +111,7 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder expressionHandler = this.defaultWebSecurityExpressionHandler; @@ -420,6 +423,8 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder mvcMatchers = createMvcMatchers(method, mvcPatterns); + Arrays.asList(mvcPatterns).stream().forEach((t) -> printWarnSecurityMessage(method, t)); + mvcMatchers.stream().forEach((t) -> t.ignore()); WebSecurity.this.ignoredRequests.addAll(mvcMatchers); return new MvcMatchersIgnoredRequestConfigurer(getApplicationContext(), mvcMatchers); } @@ -429,6 +434,38 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder antMatchers = RequestMatchers.antMatchers(method, antPatterns); + Arrays.asList(antPatterns).stream().forEach((t) -> printWarnSecurityMessage(method, t)); + antMatchers.stream().forEach((t) -> ((IgnoreRequestMatcher) t).ignore()); + return chainRequestMatchers(antMatchers); + } + + /** + * @since 5.5 + */ + @Override + public IgnoredRequestConfigurer antMatchers(String... antPatterns) { + Assert.state(!this.anyRequestConfigured, "Can't configure antMatchers after anyRequest"); + List antMatchers = RequestMatchers.antMatchers(antPatterns); + Arrays.asList(antPatterns).stream().forEach((t) -> printWarnSecurityMessage(null, t)); + antMatchers.stream().forEach((t) -> ((IgnoreRequestMatcher) t).ignore()); + return chainRequestMatchers(RequestMatchers.antMatchers(antPatterns)); + } + @Override protected IgnoredRequestConfigurer chainRequestMatchers(List requestMatchers) { WebSecurity.this.ignoredRequests.addAll(requestMatchers); @@ -442,6 +479,33 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder + * DELETE, POST, PUT work with csrf, thus is mandatory use it or it can be + * ignored/avoid with {@code csrf().disable()}, otherwise those HTTP methods + * always fail with 403. Because is critical use csrf in production, the test + * methods for those HTTP methods use {@code .with(csrf())} + */ + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .antMatchers("/something").hasRole("USER") + .antMatchers("/home").authenticated() + .antMatchers(HttpMethod.GET, "/search/alpha", "/search/beta").hasAnyRole("USER", "ADMIN", "OVERSIGHT") + .antMatchers(HttpMethod.GET, "/notification/**", "/report/**").authenticated() + .antMatchers(HttpMethod.POST).hasRole("ADMIN")//this approach only exists for 'antMatchers' + .antMatchers(HttpMethod.PUT).hasRole("ADMIN")//this approach only exists for 'antMatchers' + .antMatchers(HttpMethod.DELETE).hasRole("ADMIN")//this approach only exists for 'antMatchers' + .antMatchers("/blog").permitAll() + .antMatchers("/**").hasRole("OTHER")//should be 'authenticated()', but is used to be only applied to '/other' + .and() + .formLogin(); + // @formatter:on + } + + /** + * For the {@code PATCH} http method is not mandatory use in its test + * {@code .with(csrf())}, it because is already ignored. + */ + @Override + public void configure(WebSecurity web) throws Exception { + // @formatter:off + web.ignoring().antMatchers("/css/**", "/js/**") + .antMatchers(HttpMethod.GET, "/about", "/contact") + .antMatchers(HttpMethod.PATCH); // this approach only exists for 'antMatchers' + // @formatter:on + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Controller + static class WebUniverseController { + + @GetMapping(path = "/home") + String home(Model model) { + return "home/home"; + } + + @GetMapping(path = "/something") + String something(Model model) { + return "something/something"; + } + + @GetMapping(path = "/blog") + String blog(Model model) { + return "blog/blog"; + } + + @GetMapping(path = "/about") + String about(Model model) { + return "about/about"; + } + + @GetMapping(path = "/contact") + String contact(Model model) { + return "contact/contact"; + } + + @GetMapping(path = { "/search/alpha", "/search/beta" }) + String search(Model model) { + return "search/search"; + } + + @GetMapping(path = { "notification/alpha", "notification/beta" }) + String notification(Model model) { + return "notification/notification"; + } + + @GetMapping(path = { "/report/alpha", "/report/beta" }) + String report(Model model) { + return "report/report"; + } + + @GetMapping(path = { "/other" }) + String other(Model model) { + return "other/other"; + } + + @DeleteMapping(path = { "/delete/{id}" }) + String delete(@PathVariable String id) { + logger.info(LogMessage.format("id: %s%n", id)); + // Keep simple the approach + return "delete/delete"; + } + + @DeleteMapping(path = { "/remove/{id}" }) + String remove(@PathVariable String id) { + logger.info(LogMessage.format("id: %s%n", id)); + // Keep simple the approach + return "remove/remove"; + } + + @PostMapping(path = { "/post" }) + String post() { + // Keep simple the approach + return "post/post"; + } + + @PostMapping(path = { "/save" }) + String save() { + // Keep simple the approach + return "save/save"; + } + + @PutMapping(path = { "/put" }) + String put() { + // Keep simple the approach + return "put/put"; + } + + @PutMapping(path = { "/update" }) + String update() { + // Keep simple the approach + return "update/update"; + } + + @PatchMapping(path = { "/patch/{id}" }) + String patch(@PathVariable String id) { + logger.info(LogMessage.format("id: %s%n", id)); + // Keep simple the approach + return "patch/patch"; + } + + } + + } + + /** + * @author Manuel Jordan + * @since 5.5 + */ + @EnableWebMvc + @EnableWebSecurity + static class WebSecurityWithoutIgnoring extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().withUser(PasswordEncodedUser.user()).withUser(PasswordEncodedUser.admin()); + } + + /** + * {@code antMatchers("/**").hasRole("OTHER")} really should be + * {@code antMatchers("/**").authenticated()}, but to test that really {@code /**} + * is being applied then {@code hasRole("OTHER")} is used. + * + *

+ * DELETE, POST, PUT work with csrf, thus is mandatory use it or it can be + * ignored/avoid with {@code csrf().disable()}, otherwise those HTTP methods + * always fail with 403. Because is critical use csrf in production, the test + * methods for those HTTP methods use {@code .with(csrf())} + */ + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .antMatchers("/something").hasRole("USER") + .antMatchers("/home").authenticated() + .antMatchers(HttpMethod.GET, "/search/alpha", "/search/beta").hasAnyRole("USER", "ADMIN", "OVERSIGHT") + .antMatchers(HttpMethod.GET, "/notification/**", "/report/**").authenticated() + .antMatchers(HttpMethod.POST).hasRole("ADMIN")//this approach only exists for 'antMatchers' + .antMatchers(HttpMethod.PUT).hasRole("ADMIN")//this approach only exists for 'antMatchers' + .antMatchers(HttpMethod.DELETE).hasRole("ADMIN")//this approach only exists for 'antMatchers' + .antMatchers("/blog").permitAll() + .antMatchers("/**").hasRole("OTHER")//latest line of defense, there is no ignore settings + //should be 'authenticated()', but is used to be applied to '/other' and 'PATCH' + .and() + .formLogin(); + // @formatter:on + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Controller + static class WebUniverseController { + + @GetMapping(path = "/home") + String home(Model model) { + return "home/home"; + } + + @GetMapping(path = "/something") + String something(Model model) { + return "something/something"; + } + + @GetMapping(path = "/blog") + String blog(Model model) { + return "blog/blog"; + } + + @GetMapping(path = "/about") + String about(Model model) { + return "about/about"; + } + + @GetMapping(path = "/contact") + String contact(Model model) { + return "contact/contact"; + } + + @GetMapping(path = { "/search/alpha", "/search/beta" }) + String search(Model model) { + return "search/search"; + } + + @GetMapping(path = { "notification/alpha", "notification/beta" }) + String notification(Model model) { + return "notification/notification"; + } + + @GetMapping(path = { "/report/alpha", "/report/beta" }) + String report(Model model) { + return "report/report"; + } + + @GetMapping(path = { "/other" }) + String other(Model model) { + return "other/other"; + } + + @DeleteMapping(path = { "/delete/{id}" }) + String delete(@PathVariable String id) { + logger.info(LogMessage.format("id: %s%n", id)); + // Keep simple the approach + return "delete/delete"; + } + + @DeleteMapping(path = { "/remove/{id}" }) + String remove(@PathVariable String id) { + logger.info(LogMessage.format("id: %s%n", id)); + // Keep simple the approach + return "remove/remove"; + } + + @PostMapping(path = { "/post" }) + String post() { + // Keep simple the approach + return "post/post"; + } + + @PostMapping(path = { "/save" }) + String save() { + // Keep simple the approach + return "save/save"; + } + + @PutMapping(path = { "/put" }) + String put() { + // Keep simple the approach + return "put/put"; + } + + @PutMapping(path = { "/update" }) + String update() { + // Keep simple the approach + return "update/update"; + } + + @PatchMapping(path = { "/patch/{id}" }) + String patch(@PathVariable String id) { + logger.info(LogMessage.format("id: %s%n", id)); + // Keep simple the approach + return "patch/patch"; + } + + } + + } + + /** + * @author Manuel Jordan + * @since 5.5 + */ + @EnableWebMvc + @EnableWebSecurity + static class WebSecurityWithGlobalIgnoring extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().withUser(PasswordEncodedUser.user()).withUser(PasswordEncodedUser.admin()); + } + + /** + * {@code antMatchers("/**").hasRole("OTHER")} really should be + * {@code antMatchers("/**").authenticated()}, but to test that really {@code /**} + * is being applied then {@code hasRole("OTHER")} is used. Nevertheless through + * {@code web.ignoring().antMatchers("/**")} is it is ignored. + * + *

+ * DELETE, POST, PUT work with csrf, thus is mandatory use it or it can be + * ignored/avoid with {@code csrf().disable()}, otherwise those HTTP methods + * always fail with 403. Because is critical use csrf in production, the test + * methods for those HTTP methods use {@code .with(csrf())} + */ + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .antMatchers("/something").hasRole("USER") + .antMatchers("/home").authenticated() + .antMatchers(HttpMethod.GET, "/search/alpha", "/search/beta").hasAnyRole("USER", "ADMIN", "OVERSIGHT") + .antMatchers(HttpMethod.GET, "/notification/**", "/report/**").authenticated() + .antMatchers(HttpMethod.POST).hasRole("ADMIN")//this approach only exists for 'antMatchers' + .antMatchers(HttpMethod.PUT).hasRole("ADMIN")//this approach only exists for 'antMatchers' + .antMatchers(HttpMethod.DELETE).hasRole("ADMIN")//this approach only exists for 'antMatchers' + .antMatchers("/blog").permitAll() + .antMatchers("/**").hasRole("OTHER")//to confirm that the role is completely ignored by 'web.ignoring()' + .and() + .formLogin(); + // @formatter:on + } + + /** + * With these settings ({@code /**}, the settings on + * {@link #configure(HttpSecurity)} are completely ignored. + */ + @Override + public void configure(WebSecurity web) throws Exception { + // @formatter:off + web.ignoring().antMatchers("/**") + .antMatchers(HttpMethod.GET, "/**")// redundant, used for test output purposes + .antMatchers(HttpMethod.PATCH); // this approach only exists for 'antMatchers' + // @formatter:on + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Controller + static class WebUniverseController { + + @GetMapping(path = "/home") + String home(Model model) { + return "home/home"; + } + + @GetMapping(path = "/something") + String something(Model model) { + return "something/something"; + } + + @GetMapping(path = "/blog") + String blog(Model model) { + return "blog/blog"; + } + + @GetMapping(path = "/about") + String about(Model model) { + return "about/about"; + } + + @GetMapping(path = "/contact") + String contact(Model model) { + return "contact/contact"; + } + + @GetMapping(path = { "/search/alpha", "/search/beta" }) + String search(Model model) { + return "search/search"; + } + + @GetMapping(path = { "notification/alpha", "notification/beta" }) + String notification(Model model) { + return "notification/notification"; + } + + @GetMapping(path = { "/report/alpha", "/report/beta" }) + String report(Model model) { + return "report/report"; + } + + @GetMapping(path = { "/other" }) + String other(Model model) { + return "other/other"; + } + + @DeleteMapping(path = { "/delete/{id}" }) + String delete(@PathVariable String id) { + logger.info(LogMessage.format("id: %s%n", id)); + // Keep simple the approach + return "delete/delete"; + } + + @DeleteMapping(path = { "/remove/{id}" }) + String remove(@PathVariable String id) { + logger.info(LogMessage.format("id: %s%n", id)); + // Keep simple the approach + return "remove/remove"; + } + + @PostMapping(path = { "/post" }) + String post() { + // Keep simple the approach + return "post/post"; + } + + @PostMapping(path = { "/save" }) + String save() { + // Keep simple the approach + return "save/save"; + } + + @PutMapping(path = { "/put" }) + String put() { + // Keep simple the approach + return "put/put"; + } + + @PutMapping(path = { "/update" }) + String update() { + // Keep simple the approach + return "update/update"; + } + + @PatchMapping(path = { "/patch/{id}" }) + String patch(@PathVariable String id) { + logger.info(LogMessage.format("id: %s%n", id)); + // Keep simple the approach + return "patch/patch"; + } + + } + + } + +} diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/ignore/MvcRequestMatcherIgnoreConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/ignore/MvcRequestMatcherIgnoreConfigurationTests.java new file mode 100644 index 0000000000..26ad76d737 --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/ignore/MvcRequestMatcherIgnoreConfigurationTests.java @@ -0,0 +1,2790 @@ +/* + * Copyright 2002-2021 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 + * + * https://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.configuration.ignore; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Rule; +import org.junit.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.core.log.LogMessage; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.TestingAuthenticationToken; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +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.Authentication; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.userdetails.PasswordEncodedUser; +import org.springframework.stereotype.Controller; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; + +/** + * Test the correct output of the {@code DefaultSecurityFilterChain} class when the + * {@code web.ignoring().mvcMatchers(...)} statement is declared to ignore a mvc pattern + * working through the {@code MvcRequestMatcher} type. + * + * @author Manuel Jordan + * @since 5.5 + */ +public class MvcRequestMatcherIgnoreConfigurationTests { + + private static final Log logger = LogFactory.getLog(MvcRequestMatcherIgnoreConfigurationTests.class); + + @Rule + public final SpringTestRule spring = new SpringTestRule(); + + @Autowired + private MockMvc mockMvc; + + /** + * This test is really only based about the {@code user} and his {@code password} + * verification, the roles are ignored, it could be valid or invalid. See + * {@link WebSecurityWithIgnoring#configure(AuthenticationManagerBuilder) + * configure(AuthenticationManagerBuilder)} for more details. For the rest of the + * tests based on the {@link WebSecurityWithIgnoring} class, the {@code user} and his + * {@code password} are ignored, therefore the tests are based on the roles to pass or + * fail. + * @throws Exception exception + */ + @Test + public void webSecurityWithIgnoringAuthentication() throws Exception { + logger.info("webSecurityWithIgnoringAuthentication [Test]"); + this.spring.register(WebSecurityWithIgnoring.class).autowire(); + + AuthenticationManager authenticationManager = this.spring.getContext().getBean(AuthenticationManager.class); + + // @formatter:off + logger.info(LogMessage.format("authenticationManager [CanonicalName]: %s%n", + authenticationManager.getClass().getCanonicalName())); + Authentication authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"))); + assertThat(authentication.isAuthenticated()).isTrue(); + + authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "user", "password", AuthorityUtils.createAuthorityList("ROLE_NOT_DECLARED"))); + assertThat(authentication.isAuthenticated()).isTrue(); + + authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "admin", "password", AuthorityUtils.createAuthorityList("ROLE_USER", "ROLE_ADMIN"))); + assertThat(authentication.isAuthenticated()).isTrue(); + + try { + authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "ghost", "password", AuthorityUtils.createAuthorityList("ROLE_GHOST"))); + } + catch (BadCredentialsException ex) { + assertThat(ex.getMessage()).isEqualTo("Bad credentials"); + assertThat(authentication).isNull(); + } + + try { + authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "oversight", "password", AuthorityUtils.createAuthorityList("ROLE_OVERSIGHT"))); + } + catch (BadCredentialsException ex) { + assertThat(ex.getMessage()).isEqualTo("Bad credentials"); + assertThat(authentication).isNull(); + } + + try { + authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "other", "password", AuthorityUtils.createAuthorityList("ROLE_OTHER"))); + } + catch (BadCredentialsException ex) { + assertThat(ex.getMessage()).isEqualTo("Bad credentials"); + assertThat(authentication).isNull(); + } + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithIgnoringAuthentication() + */ + @Test + public void webSecurityWithIgnoringForSomething() throws Exception { + logger.info("webSecurityWithIgnoringForSomething [Test]"); + this.spring.register(WebSecurityWithIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("something/something")) + .andExpect(forwardedUrl("something/something")) + .andReturn(); + + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("something/something")) + .andExpect(forwardedUrl("something/something")) + .andReturn(); + + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithIgnoringAuthentication() + */ + @Test + public void webSecurityWithIgnoringForHome() throws Exception { + logger.info("webSecurityWithIgnoringForHome [Test]"); + this.spring.register(WebSecurityWithIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithIgnoringAuthentication() + */ + @Test + public void webSecurityWithIgnoringForSearch() throws Exception { + logger.info("webSecurityWithIgnoringForSearch [Test]"); + this.spring.register(WebSecurityWithIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithIgnoringAuthentication() + */ + @Test + public void webSecurityWithIgnoringForNotification() throws Exception { + logger.info("webSecurityWithIgnoringForNotification [Test]"); + this.spring.register(WebSecurityWithIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithIgnoringAuthentication() + */ + @Test + public void webSecurityWithIgnoringForReport() throws Exception { + logger.info("webSecurityWithIgnoringForReport [Test]"); + this.spring.register(WebSecurityWithIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithIgnoringAuthentication() + */ + @Test + public void webSecurityWithIgnoringForContact() throws Exception { + logger.info("webSecurityWithIgnoringForContact [Test]"); + this.spring.register(WebSecurityWithIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("contact/contact")) + .andExpect(forwardedUrl("contact/contact")) + .andReturn(); + + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("contact/contact")) + .andExpect(forwardedUrl("contact/contact")) + .andReturn(); + + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("contact/contact")) + .andExpect(forwardedUrl("contact/contact")) + .andReturn(); + + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("contact/contact")) + .andExpect(forwardedUrl("contact/contact")) + .andReturn(); + + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("contact/contact")) + .andExpect(forwardedUrl("contact/contact")) + .andReturn(); + + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("contact/contact")) + .andExpect(forwardedUrl("contact/contact")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithIgnoringAuthentication() + */ + @Test + public void webSecurityWithIgnoringForAbout() throws Exception { + logger.info("webSecurityWithIgnoringForAbout [Test]"); + this.spring.register(WebSecurityWithIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("about/about")) + .andExpect(forwardedUrl("about/about")) + .andReturn(); + + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("about/about")) + .andExpect(forwardedUrl("about/about")) + .andReturn(); + + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("about/about")) + .andExpect(forwardedUrl("about/about")) + .andReturn(); + + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("about/about")) + .andExpect(forwardedUrl("about/about")) + .andReturn(); + + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("about/about")) + .andExpect(forwardedUrl("about/about")) + .andReturn(); + + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("about/about")) + .andExpect(forwardedUrl("about/about")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithIgnoringAuthentication() + */ + @Test + public void webSecurityWithIgnoringForBlog() throws Exception { + logger.info("webSecurityWithIgnoringForBlog [Test]"); + this.spring.register(WebSecurityWithIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithIgnoringAuthentication() + */ + @Test + public void webSecurityWithIgnoringForOther() throws Exception { + logger.info("webSecurityWithIgnoringForOther [Test]"); + this.spring.register(WebSecurityWithIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("other/other")) + .andExpect(forwardedUrl("other/other")) + .andReturn(); + // @formatter:on + } + + /** + * This test is really only based about the {@code user} and his {@code password} + * verification, the roles are ignored, it could be valid or invalid. See + * {@link WebSecurityWithoutIgnoring#configure(AuthenticationManagerBuilder) + * configure(AuthenticationManagerBuilder)} for more details. For the rest of the + * tests based on the {@link WebSecurityWithoutIgnoring} class, the {@code user} and + * his {@code password} are ignored, therefore the test is based on the roles to pass + * or fail. + * @throws Exception exception + */ + @Test + public void webSecurityWithoutIgnoringAuthentication() throws Exception { + logger.info("webSecurityWithoutIgnoringAuthentication [Test]"); + this.spring.register(WebSecurityWithoutIgnoring.class).autowire(); + + AuthenticationManager authenticationManager = this.spring.getContext().getBean(AuthenticationManager.class); + + // @formatter:off + logger.info(LogMessage.format("authenticationManager [CanonicalName]: %s%n", + authenticationManager.getClass().getCanonicalName())); + Authentication authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"))); + assertThat(authentication.isAuthenticated()).isTrue(); + + authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "user", "password", AuthorityUtils.createAuthorityList("ROLE_NOT_DECLARED"))); + assertThat(authentication.isAuthenticated()).isTrue(); + + authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "admin", "password", AuthorityUtils.createAuthorityList("ROLE_USER", "ROLE_ADMIN"))); + assertThat(authentication.isAuthenticated()).isTrue(); + + try { + authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "ghost", "password", AuthorityUtils.createAuthorityList("ROLE_GHOST"))); + } + catch (BadCredentialsException ex) { + assertThat(ex.getMessage()).isEqualTo("Bad credentials"); + assertThat(authentication).isNull(); + } + + try { + authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "oversight", "password", AuthorityUtils.createAuthorityList("ROLE_OVERSIGHT"))); + } + catch (BadCredentialsException ex) { + assertThat(ex.getMessage()).isEqualTo("Bad credentials"); + assertThat(authentication).isNull(); + } + + try { + authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "other", "password", AuthorityUtils.createAuthorityList("ROLE_OTHER"))); + } + catch (BadCredentialsException ex) { + assertThat(ex.getMessage()).isEqualTo("Bad credentials"); + assertThat(authentication).isNull(); + } + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithoutIgnoringAuthentication() + */ + @Test + public void webSecurityWithoutIgnoringForSomething() throws Exception { + logger.info("webSecurityWithoutIgnoringForSomething [Test]"); + this.spring.register(WebSecurityWithoutIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("something/something")) + .andExpect(forwardedUrl("something/something")) + .andReturn(); + + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("something/something")) + .andExpect(forwardedUrl("something/something")) + .andReturn(); + + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithoutIgnoringAuthentication() + */ + @Test + public void webSecurityWithoutIgnoringForHome() throws Exception { + logger.info("webSecurityWithoutIgnoringForHome [Test]"); + this.spring.register(WebSecurityWithoutIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithoutIgnoringAuthentication() + */ + @Test + public void webSecurityWithoutIgnoringForSearch() throws Exception { + logger.info("webSecurityWithoutIgnoringForSearch [Test]"); + this.spring.register(WebSecurityWithoutIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithoutIgnoringAuthentication() + */ + @Test + public void webSecurityWithoutIgnoringForNotification() throws Exception { + logger.info("webSecurityWithoutIgnoringForNotification [Test]"); + this.spring.register(WebSecurityWithoutIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithoutIgnoringAuthentication() + */ + @Test + public void webSecurityWithoutIgnoringForReport() throws Exception { + logger.info("webSecurityWithoutIgnoringForReport [Test]"); + this.spring.register(WebSecurityWithoutIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithoutIgnoringAuthentication() + */ + @Test + public void webSecurityWithoutIgnoringForContact() throws Exception { + logger.info("webSecurityWithoutIgnoringForContact [Test]"); + this.spring.register(WebSecurityWithoutIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("contact/contact")) + .andExpect(forwardedUrl("contact/contact")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithoutIgnoringAuthentication() + */ + @Test + public void webSecurityWithoutIgnoringForAbout() throws Exception { + logger.info("webSecurityWithoutIgnoringForAbout [Test]"); + this.spring.register(WebSecurityWithoutIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("about/about")) + .andExpect(forwardedUrl("about/about")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithoutIgnoringAuthentication() + */ + @Test + public void webSecurityWithoutIgnoringForBlog() throws Exception { + logger.info("webSecurityWithoutIgnoringForBlog [Test]"); + this.spring.register(WebSecurityWithoutIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithoutIgnoringAuthentication() + */ + @Test + public void webSecurityWithoutIgnoringForOther() throws Exception { + logger.info("webSecurityWithoutIgnoringForOther [Test]"); + this.spring.register(WebSecurityWithoutIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isForbidden()) + .andReturn(); + + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("other/other")) + .andExpect(forwardedUrl("other/other")) + .andReturn(); + // @formatter:on + } + + /** + * This test is really only based about the {@code user} and his {@code password} + * verification, the roles are ignored, it could be valid or invalid. See + * {@link WebSecurityWithGlobalIgnoring#configure(AuthenticationManagerBuilder) + * configure(AuthenticationManagerBuilder)} for more details. For the rest of the + * tests based on the {@link WebSecurityWithGlobalIgnoring} class, the {@code user} + * and his {@code password} are ignored, therefore the test is based on the roles to + * pass or fail. + * @throws Exception exception + */ + @Test + public void webSecurityWithGlobalIgnoringAuthentication() throws Exception { + logger.info("webSecurityWithGlobalIgnoringAuthentication [Test]"); + this.spring.register(WebSecurityWithGlobalIgnoring.class).autowire(); + + AuthenticationManager authenticationManager = this.spring.getContext().getBean(AuthenticationManager.class); + + // @formatter:off + logger.info(LogMessage.format("authenticationManager [CanonicalName]: %s%n", + authenticationManager.getClass().getCanonicalName())); + Authentication authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"))); + assertThat(authentication.isAuthenticated()).isTrue(); + + authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "user", "password", AuthorityUtils.createAuthorityList("ROLE_NOT_DECLARED"))); + assertThat(authentication.isAuthenticated()).isTrue(); + + authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "admin", "password", AuthorityUtils.createAuthorityList("ROLE_USER", "ROLE_ADMIN"))); + assertThat(authentication.isAuthenticated()).isTrue(); + + try { + authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "ghost", "password", AuthorityUtils.createAuthorityList("ROLE_GHOST"))); + } + catch (BadCredentialsException ex) { + assertThat(ex.getMessage()).isEqualTo("Bad credentials"); + assertThat(authentication).isNull(); + } + + try { + authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "oversight", "password", AuthorityUtils.createAuthorityList("ROLE_OVERSIGHT"))); + } + catch (BadCredentialsException ex) { + assertThat(ex.getMessage()).isEqualTo("Bad credentials"); + assertThat(authentication).isNull(); + } + + try { + authentication = null; + authentication = + authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + "other", "password", AuthorityUtils.createAuthorityList("ROLE_OTHER"))); + } + catch (BadCredentialsException ex) { + assertThat(ex.getMessage()).isEqualTo("Bad credentials"); + assertThat(authentication).isNull(); + } + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithGlobalIgnoringAuthentication() + */ + @Test + public void webSecurityWithGlobalIgnoringForSomething() throws Exception { + logger.info("webSecurityWithGlobalIgnoringForSomething [Test]"); + this.spring.register(WebSecurityWithGlobalIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("something/something")) + .andExpect(forwardedUrl("something/something")) + .andReturn(); + + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("something/something")) + .andExpect(forwardedUrl("something/something")) + .andReturn(); + + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("something/something")) + .andExpect(forwardedUrl("something/something")) + .andReturn(); + + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("something/something")) + .andExpect(forwardedUrl("something/something")) + .andReturn(); + + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("something/something")) + .andExpect(forwardedUrl("something/something")) + .andReturn(); + + this.mockMvc.perform( + get("/something") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("something/something")) + .andExpect(forwardedUrl("something/something")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithGlobalIgnoringAuthentication() + */ + @Test + public void webSecurityWithGlobalIgnoringForHome() throws Exception { + logger.info("webSecurityWithGlobalIgnoringForHome [Test]"); + this.spring.register(WebSecurityWithGlobalIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + + this.mockMvc.perform( + get("/home") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("home/home")) + .andExpect(forwardedUrl("home/home")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithGlobalIgnoringAuthentication() + */ + @Test + public void webSecurityWithGlobalIgnoringForSearch() throws Exception { + logger.info("webSecurityWithGlobalIgnoringForSearch [Test]"); + this.spring.register(WebSecurityWithGlobalIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/alpha") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + + this.mockMvc.perform( + get("/search/beta") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("search/search")) + .andExpect(forwardedUrl("search/search")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithGlobalIgnoringAuthentication() + */ + @Test + public void webSecurityWithGlobalIgnoringForNotification() throws Exception { + logger.info("webSecurityWithGlobalIgnoringForNotification [Test]"); + this.spring.register(WebSecurityWithGlobalIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/alpha") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + + this.mockMvc.perform( + get("/notification/beta") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("notification/notification")) + .andExpect(forwardedUrl("notification/notification")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithGlobalIgnoringAuthentication() + */ + @Test + public void webSecurityWithGlobalIgnoringForReport() throws Exception { + logger.info("webSecurityWithGlobalIgnoringForReport [Test]"); + this.spring.register(WebSecurityWithGlobalIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/alpha") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + + this.mockMvc.perform( + get("/report/beta") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("report/report")) + .andExpect(forwardedUrl("report/report")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithGlobalIgnoringAuthentication() + */ + @Test + public void webSecurityWithGlobalIgnoringForContact() throws Exception { + logger.info("webSecurityWithGlobalIgnoringForContact [Test]"); + this.spring.register(WebSecurityWithGlobalIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("contact/contact")) + .andExpect(forwardedUrl("contact/contact")) + .andReturn(); + + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("contact/contact")) + .andExpect(forwardedUrl("contact/contact")) + .andReturn(); + + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("contact/contact")) + .andExpect(forwardedUrl("contact/contact")) + .andReturn(); + + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("contact/contact")) + .andExpect(forwardedUrl("contact/contact")) + .andReturn(); + + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("contact/contact")) + .andExpect(forwardedUrl("contact/contact")) + .andReturn(); + + this.mockMvc.perform( + get("/contact") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("contact/contact")) + .andExpect(forwardedUrl("contact/contact")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithGlobalIgnoringAuthentication() + */ + @Test + public void webSecurityWithGlobalIgnoringForAbout() throws Exception { + logger.info("webSecurityWithGlobalIgnoringForAbout [Test]"); + this.spring.register(WebSecurityWithGlobalIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("about/about")) + .andExpect(forwardedUrl("about/about")) + .andReturn(); + + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("about/about")) + .andExpect(forwardedUrl("about/about")) + .andReturn(); + + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("about/about")) + .andExpect(forwardedUrl("about/about")) + .andReturn(); + + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("about/about")) + .andExpect(forwardedUrl("about/about")) + .andReturn(); + + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("about/about")) + .andExpect(forwardedUrl("about/about")) + .andReturn(); + + this.mockMvc.perform( + get("/about") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("about/about")) + .andExpect(forwardedUrl("about/about")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithGlobalIgnoringAuthentication() + */ + @Test + public void webSecurityWithGlobalIgnoringForBlog() throws Exception { + logger.info("webSecurityWithGlobalIgnoringForBlog [Test]"); + this.spring.register(WebSecurityWithGlobalIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + + this.mockMvc.perform( + get("/blog") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("blog/blog")) + .andExpect(forwardedUrl("blog/blog")) + .andReturn(); + // @formatter:on + } + + /** + * @throws Exception exception + * @see #webSecurityWithGlobalIgnoringAuthentication() + */ + @Test + public void webSecurityWithGlobalIgnoringForOther() throws Exception { + logger.info("webSecurityWithGlobalIgnoringForOther [Test]"); + this.spring.register(WebSecurityWithGlobalIgnoring.class).autowire(); + + // @formatter:off + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_USER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("other/other")) + .andExpect(forwardedUrl("other/other")) + .andReturn(); + + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("user", "password", "ROLE_NOT_DECLARED")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("other/other")) + .andExpect(forwardedUrl("other/other")) + .andReturn(); + + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("admin", "password", "ROLE_USER", "ROLE_ADMIN")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("other/other")) + .andExpect(forwardedUrl("other/other")) + .andReturn(); + + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("ghost", "password", "ROLE_GHOST")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("other/other")) + .andExpect(forwardedUrl("other/other")) + .andReturn(); + + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("oversight", "password", "ROLE_OVERSIGHT")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("other/other")) + .andExpect(forwardedUrl("other/other")) + .andReturn(); + + this.mockMvc.perform( + get("/other") + .with(authentication(new TestingAuthenticationToken("other", "password", "ROLE_OTHER")))) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(view().name("other/other")) + .andExpect(forwardedUrl("other/other")) + .andReturn(); + // @formatter:on + } + + /** + * @author Manuel Jordan + * @since 5.5 + */ + @EnableWebMvc + @EnableWebSecurity + static class WebSecurityWithIgnoring extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().withUser(PasswordEncodedUser.user()).withUser(PasswordEncodedUser.admin()); + } + + /** + * {@code mvcMatchers("/**").hasRole("OTHER")} really should be + * {@code mvcMatchers("/**").authenticated()}, but to test that really {@code /**} + * is being applied then {@code hasRole("OTHER")} is used + */ + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .mvcMatchers("/something").hasRole("USER") + .mvcMatchers("/home").authenticated() + .mvcMatchers(HttpMethod.GET, "/search/alpha", "/search/beta").hasAnyRole("USER", "ADMIN", "OVERSIGHT") + .mvcMatchers(HttpMethod.GET, "/notification/**", "/report/**").authenticated() + .mvcMatchers("/blog").permitAll() + .mvcMatchers("/**").hasRole("OTHER")//should be 'authenticated()', but is used to be only applied to '/other' + .and() + .formLogin(); + // @formatter:on + } + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().mvcMatchers("/css/**", "/js/**").mvcMatchers(HttpMethod.GET, "/about", "/contact"); + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Controller + static class WebUniverseController { + + @GetMapping(path = "/home") + String home(Model model) { + return "home/home"; + } + + @GetMapping(path = "/something") + String something(Model model) { + return "something/something"; + } + + @GetMapping(path = "/blog") + String blog(Model model) { + return "blog/blog"; + } + + @GetMapping(path = "/about") + String about(Model model) { + return "about/about"; + } + + @GetMapping(path = "/contact") + String contact(Model model) { + return "contact/contact"; + } + + @GetMapping(path = { "/search/alpha", "/search/beta" }) + String search(Model model) { + return "search/search"; + } + + @GetMapping(path = { "notification/alpha", "notification/beta" }) + String notification(Model model) { + return "notification/notification"; + } + + @GetMapping(path = { "/report/alpha", "/report/beta" }) + String report(Model model) { + return "report/report"; + } + + @GetMapping(path = { "/other" }) + String other(Model model) { + return "other/other"; + } + + } + + } + + /** + * @author Manuel Jordan + * @since 5.5 + */ + @EnableWebMvc + @EnableWebSecurity + static class WebSecurityWithoutIgnoring extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().withUser(PasswordEncodedUser.user()).withUser(PasswordEncodedUser.admin()); + } + + /** + * {@code mvcMatchers("/**").hasRole("OTHER")} really should be + * {@code mvcMatchers("/**").authenticated()}, but to test that really {@code /**} + * is being applied then {@code hasRole("OTHER")} is used + */ + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .mvcMatchers("/something").hasRole("USER") + .mvcMatchers("/home").authenticated() + .mvcMatchers(HttpMethod.GET, "/search/alpha", "/search/beta").hasAnyRole("USER", "ADMIN", "OVERSIGHT") + .mvcMatchers(HttpMethod.GET, "/notification/**", "/report/**").authenticated() + .mvcMatchers("/blog").permitAll() + .mvcMatchers("/**").hasRole("OTHER")//latest line of defense, there is no ignore settings + //should be 'authenticated()', but is used to be only applied to '/other' + .and() + .formLogin(); + // @formatter:on + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Controller + static class WebUniverseController { + + @GetMapping(path = "/home") + String home(Model model) { + return "home/home"; + } + + @GetMapping(path = "/something") + String something(Model model) { + return "something/something"; + } + + @GetMapping(path = "/blog") + String blog(Model model) { + return "blog/blog"; + } + + @GetMapping(path = "/about") + String about(Model model) { + return "about/about"; + } + + @GetMapping(path = "/contact") + String contact(Model model) { + return "contact/contact"; + } + + @GetMapping(path = { "/search/alpha", "/search/beta" }) + String search(Model model) { + return "search/search"; + } + + @GetMapping(path = { "notification/alpha", "notification/beta" }) + String notification(Model model) { + return "notification/notification"; + } + + @GetMapping(path = { "/report/alpha", "/report/beta" }) + String report(Model model) { + return "report/report"; + } + + @GetMapping(path = { "/other" }) + String other(Model model) { + return "other/other"; + } + + } + + } + + /** + * @author Manuel Jordan + * @since 5.5 + */ + @EnableWebMvc + @EnableWebSecurity + static class WebSecurityWithGlobalIgnoring extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().withUser(PasswordEncodedUser.user()).withUser(PasswordEncodedUser.admin()); + } + + /** + * {@code mvcMatchers("/**").hasRole("OTHER")} really should be + * {@code mvcMatchers("/**").authenticated()}, but to test that really {@code /**} + * is being applied then {@code hasRole("OTHER")} is used. Nevertheless through + * {@code web.ignoring().mvcMatchers("/**")} is it is ignored. + */ + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .mvcMatchers("/something").hasRole("USER") + .mvcMatchers("/home").authenticated() + .mvcMatchers(HttpMethod.GET, "/search/alpha", "/search/beta").hasAnyRole("USER", "ADMIN", "OVERSIGHT") + .mvcMatchers(HttpMethod.GET, "/notification/**", "/report/**").authenticated() + .mvcMatchers("/blog").permitAll() + .mvcMatchers("/**").hasRole("OTHER")//to confirm that the role is completely ignored by 'web.ignoring()' + .and() + .formLogin(); + // @formatter:on + } + + /** + * With these settings ({@code /**}, the settings on + * {@link #configure(HttpSecurity)} are completely ignored. + */ + @Override + public void configure(WebSecurity web) throws Exception { + // @formatter:off + web.ignoring().mvcMatchers("/**") + .mvcMatchers(HttpMethod.GET, "/**"); // redundant, used for test output purposes + // @formatter:on + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Controller + static class WebUniverseController { + + @GetMapping(path = "/home") + String home(Model model) { + return "home/home"; + } + + @GetMapping(path = "/something") + String something(Model model) { + return "something/something"; + } + + @GetMapping(path = "/blog") + String blog(Model model) { + return "blog/blog"; + } + + @GetMapping(path = "/about") + String about(Model model) { + return "about/about"; + } + + @GetMapping(path = "/contact") + String contact(Model model) { + return "contact/contact"; + } + + @GetMapping(path = { "/search/alpha", "/search/beta" }) + String search(Model model) { + return "search/search"; + } + + @GetMapping(path = { "notification/alpha", "notification/beta" }) + String notification(Model model) { + return "notification/notification"; + } + + @GetMapping(path = { "/report/alpha", "/report/beta" }) + String report(Model model) { + return "report/report"; + } + + @GetMapping(path = { "/other" }) + String other(Model model) { + return "other/other"; + } + + } + + } + +} diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/ignore/package-info.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/ignore/package-info.java new file mode 100644 index 0000000000..80f603937b --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/ignore/package-info.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2021 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 + * + * https://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. + */ + +/** + * Test package for path patterns that must be ignored by Spring Security and must be + * indicated/notified through the output, it thanks to the + * DefaultSecurityFilterChain's constructor. + * + *

+ * NOTE: be advised that to test if a path(s) was really ignored or not, by + * simplicity, is checking the output shown in the test report, it based with the pattern + * "Will not secure /ABC", where ABC was defined through the + * web.ignoring() approach. Is very important edit the + * logback-test.xml file (of this module) to change + * level="${sec.log.level:-WARN}" to + * level="${sec.log.level:-INFO}" + * + *

+ * In the handler methods do not return the view name (i.e: + * return "something") based on the path value (i.e: + * @GetMapping(path = "/something")), otherwise the tests fail with: + * + *

+ * javax.servlet.ServletException:
+ * Circular view path [something]:
+ * would dispatch back to the current handler URL [/something] again.
+ * Check your ViewResolver setup!
+ * (Hint: This may be the result of an unspecified view, due to default view name generation.)
+ * 
+ * + * That's why the all handler methods are based with the + * return "something/something" pattern. + * + * @author Manuel Jordan + * @since 5.5 + */ +package org.springframework.security.config.annotation.web.configuration.ignore; diff --git a/web/src/main/java/org/springframework/security/web/DefaultSecurityFilterChain.java b/web/src/main/java/org/springframework/security/web/DefaultSecurityFilterChain.java index 1961bf84fd..7bb08a90c5 100644 --- a/web/src/main/java/org/springframework/security/web/DefaultSecurityFilterChain.java +++ b/web/src/main/java/org/springframework/security/web/DefaultSecurityFilterChain.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2021 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. @@ -27,6 +27,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.log.LogMessage; +import org.springframework.security.web.server.restriction.IgnoreRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; /** @@ -48,7 +49,18 @@ public final class DefaultSecurityFilterChain implements SecurityFilterChain { } public DefaultSecurityFilterChain(RequestMatcher requestMatcher, List filters) { - logger.info(LogMessage.format("Will secure %s with %s", requestMatcher, filters)); + if (requestMatcher instanceof IgnoreRequestMatcher) { + IgnoreRequestMatcher ignoreRequestMatcher = (IgnoreRequestMatcher) requestMatcher; + if (ignoreRequestMatcher.isIgnore()) { + logger.info(LogMessage.format("Will not secure %s with %s", requestMatcher, filters)); + } + else { + logger.info(LogMessage.format("Will secure %s with %s", requestMatcher, filters)); + } + } + else { + logger.info(LogMessage.format("Will secure %s with %s", requestMatcher, filters)); + } this.requestMatcher = requestMatcher; this.filters = new ArrayList<>(filters); } diff --git a/web/src/main/java/org/springframework/security/web/server/restriction/IgnoreRequestMatcher.java b/web/src/main/java/org/springframework/security/web/server/restriction/IgnoreRequestMatcher.java new file mode 100644 index 0000000000..afed0c12c8 --- /dev/null +++ b/web/src/main/java/org/springframework/security/web/server/restriction/IgnoreRequestMatcher.java @@ -0,0 +1,37 @@ +/* + * Copyright 2002-2021 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 + * + * https://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.web.server.restriction; + +/** + * Indicates if the path should be ignored or not by Spring Security. + * + * @author Manuel Jordan + * @since 5.5 + */ +public interface IgnoreRequestMatcher { + + /** + * Establishes the path must be ignored. + */ + void ignore(); + + /** + * If the path should be ignored or not. + */ + boolean isIgnore(); + +} diff --git a/web/src/main/java/org/springframework/security/web/servlet/util/matcher/MvcRequestMatcher.java b/web/src/main/java/org/springframework/security/web/servlet/util/matcher/MvcRequestMatcher.java index 70c96faba5..a4b084d7e1 100644 --- a/web/src/main/java/org/springframework/security/web/servlet/util/matcher/MvcRequestMatcher.java +++ b/web/src/main/java/org/springframework/security/web/servlet/util/matcher/MvcRequestMatcher.java @@ -21,6 +21,7 @@ import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.springframework.http.HttpMethod; +import org.springframework.security.web.server.restriction.IgnoreRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestVariablesExtractor; import org.springframework.util.AntPathMatcher; @@ -44,9 +45,10 @@ import org.springframework.web.util.UrlPathHelper; * @author Rob Winch * @author Eddú Meléndez * @author Evgeniy Cheban + * @author Manuel Jordan * @since 4.1.1 */ -public class MvcRequestMatcher implements RequestMatcher, RequestVariablesExtractor { +public class MvcRequestMatcher implements RequestMatcher, RequestVariablesExtractor, IgnoreRequestMatcher { private final DefaultMatcher defaultMatcher = new DefaultMatcher(); @@ -58,9 +60,12 @@ public class MvcRequestMatcher implements RequestMatcher, RequestVariablesExtrac private String servletPath; + private boolean ignore; + public MvcRequestMatcher(HandlerMappingIntrospector introspector, String pattern) { this.introspector = introspector; this.pattern = pattern; + this.ignore = false; } @Override @@ -129,6 +134,16 @@ public class MvcRequestMatcher implements RequestMatcher, RequestVariablesExtrac return this.servletPath; } + @Override + public void ignore() { + this.ignore = true; + } + + @Override + public boolean isIgnore() { + return this.ignore; + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/web/src/main/java/org/springframework/security/web/util/matcher/AntPathRequestMatcher.java b/web/src/main/java/org/springframework/security/web/util/matcher/AntPathRequestMatcher.java index 49aed04478..4461cdf89a 100644 --- a/web/src/main/java/org/springframework/security/web/util/matcher/AntPathRequestMatcher.java +++ b/web/src/main/java/org/springframework/security/web/util/matcher/AntPathRequestMatcher.java @@ -22,6 +22,7 @@ import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.springframework.http.HttpMethod; +import org.springframework.security.web.server.restriction.IgnoreRequestMatcher; import org.springframework.util.AntPathMatcher; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -49,10 +50,11 @@ import org.springframework.web.util.UrlPathHelper; * @author Rob Winch * @author Eddú Meléndez * @author Evgeniy Cheban + * @author Manuel Jordan * @since 3.1 * @see org.springframework.util.AntPathMatcher */ -public final class AntPathRequestMatcher implements RequestMatcher, RequestVariablesExtractor { +public final class AntPathRequestMatcher implements RequestMatcher, RequestVariablesExtractor, IgnoreRequestMatcher { private static final String MATCH_ALL = "/**"; @@ -66,6 +68,8 @@ public final class AntPathRequestMatcher implements RequestMatcher, RequestVaria private final UrlPathHelper urlPathHelper; + private boolean ignore; + /** * Creates a matcher with the specific pattern which will match all HTTP methods in a * case sensitive manner. @@ -131,6 +135,7 @@ public final class AntPathRequestMatcher implements RequestMatcher, RequestVaria this.pattern = pattern; this.httpMethod = StringUtils.hasText(httpMethod) ? HttpMethod.valueOf(httpMethod) : null; this.urlPathHelper = urlPathHelper; + this.ignore = false; } /** @@ -170,6 +175,16 @@ public final class AntPathRequestMatcher implements RequestMatcher, RequestVaria return MatchResult.match(this.matcher.extractUriTemplateVariables(url)); } + @Override + public void ignore() { + this.ignore = true; + } + + @Override + public boolean isIgnore() { + return this.ignore; + } + private String getRequestPath(HttpServletRequest request) { if (this.urlPathHelper != null) { return this.urlPathHelper.getPathWithinApplication(request);