diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/serverless/web/RequestResponseTests.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/serverless/web/RequestResponseTests.java index 23941a50f..07bd8b5eb 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/serverless/web/RequestResponseTests.java +++ b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/serverless/web/RequestResponseTests.java @@ -53,6 +53,15 @@ public class RequestResponseTests { this.mvc.stop(); } + @Test + public void validateAccessDeniedWithCustomHandler() throws Exception { + HttpServletRequest request = new ProxyHttpServletRequest(null, "GET", "/foo"); + ProxyHttpServletResponse response = new ProxyHttpServletResponse(); + mvc.service(request, response); + assertThat(response.getErrorMessage()).isEqualTo("Can't touch this"); + assertThat(response.getStatus()).isEqualTo(403); + } + @Test public void validateGetListOfPojos() throws Exception { HttpServletRequest request = new ProxyHttpServletRequest(null, "GET", "/pets"); diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetStoreSpringAppConfig.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetStoreSpringAppConfig.java index 91a59e19c..4dcff017c 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetStoreSpringAppConfig.java +++ b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetStoreSpringAppConfig.java @@ -17,32 +17,29 @@ package org.springframework.cloud.function.test.app; import java.io.IOException; -import java.util.ArrayList; import java.util.Collections; -import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.web.DefaultSecurityFilterChain; import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.context.SecurityContextHolderFilter; -import org.springframework.security.web.csrf.CsrfFilter; import org.springframework.web.filter.GenericFilterBean; import org.springframework.web.servlet.HandlerAdapter; import org.springframework.web.servlet.HandlerMapping; @@ -73,33 +70,10 @@ public class PetStoreSpringAppConfig { return new RequestMappingHandlerAdapter(); } - @Bean - public BeanPostProcessor post() { - return new BeanPostProcessor() { - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - if (beanName.equals("securityFilterChain")) { - DefaultSecurityFilterChain chain = (DefaultSecurityFilterChain) bean; - ArrayList filters = new ArrayList<>(); - chain.getFilters().forEach(f -> { - if (!(f instanceof CsrfFilter)) { - filters.add(f); - } - }); - bean = new DefaultSecurityFilterChain(chain.getRequestMatcher(), filters); - } - //System.out.println(beanName); - return bean; - } - }; - } - - @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - http + http.csrf().disable() // need for POST .addFilterBefore(new GenericFilterBean() { - @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { @@ -112,22 +86,24 @@ public class PetStoreSpringAppConfig { } }, SecurityContextHolderFilter.class) .authorizeHttpRequests((requests) -> requests - .requestMatchers("/", "/pets", "/pets/").permitAll() + .requestMatchers("/", "/pets", "/pets/").hasAnyAuthority("USER") + .requestMatchers("/foo").hasAnyAuthority("FOO") .anyRequest().authenticated() ) + .exceptionHandling().accessDeniedHandler(accessDeniedHandler()).and() .logout((logout) -> logout.permitAll()); return http.build(); } @Bean - public Filter filter() { - return new Filter() { + public AccessDeniedHandler accessDeniedHandler() { + + return new AccessDeniedHandler() { @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - System.out.println("FILTER ===> Hello from: " + request.getLocalAddr()); - chain.doFilter(request, response); + public void handle(HttpServletRequest request, HttpServletResponse response, + AccessDeniedException accessDeniedException) throws IOException, ServletException { + response.sendError(403, "Can't touch this"); } }; } diff --git a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetsController.java b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetsController.java index 664ddee26..17c49d9d7 100644 --- a/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetsController.java +++ b/spring-cloud-function-adapters/spring-cloud-function-serverless-web/src/test/java/org/springframework/cloud/function/test/app/PetsController.java @@ -16,11 +16,15 @@ package org.springframework.cloud.function.test.app; +import java.io.IOException; import java.security.Principal; import java.util.Optional; import java.util.UUID; +import org.springframework.context.annotation.Bean; import org.springframework.http.HttpStatus; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -30,6 +34,10 @@ import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + @RestController @EnableWebMvc public class PetsController { @@ -78,6 +86,16 @@ public class PetsController { return newPet; } + @RequestMapping(path = "/foo", method = RequestMethod.GET) + public Pet foo() { + Pet newPet = new Pet(); + newPet.setId(UUID.randomUUID().toString()); + newPet.setBreed(PetData.getRandomBreed()); + newPet.setDateOfBirth(PetData.getRandomDoB()); + newPet.setName(PetData.getRandomName()); + return newPet; + } + @ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "No such Dog") // 404 public class DogNotFoundException extends RuntimeException { // ...