From 4018d45a2ccadd89cf4baadd5158e8f8e78e537a Mon Sep 17 00:00:00 2001 From: maibin Date: Mon, 2 Jan 2017 11:06:44 +0100 Subject: [PATCH] SecurityContextHolder + @Async fixes and improvements (#930) * @Async and Spring Security * @Async with SecurityContext propagated * Spring and @Async * Simulated Annealing algorithm * Simulated Annealing algorithm * Rebase * Rebase * SA further fixes * Slope One plus package refactoring * SlopeOne refactoring * Async improvements and fixes * Remove unnecessary bean * Final fixes to Spring Security @Async * Async Spring MVC --- .../baeldung/spring/SecurityJavaConfig.java | 13 ++----- .../java/org/baeldung/spring/WebConfig.java | 4 ++- .../web/controller/AsyncController.java | 32 +++++++++-------- .../baeldung/web/service/AsyncService.java | 4 +-- .../web/service/AsyncServiceImpl.java | 34 +++++++++---------- .../src/main/resources/webSecurityConfig.xml | 5 --- .../src/main/webapp/WEB-INF/web.xml | 4 ++- .../org/baeldung/web/AsyncControllerTest.java | 7 ++-- 8 files changed, 46 insertions(+), 57 deletions(-) diff --git a/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java b/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java index 448968a6c8..8766aab3b6 100644 --- a/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java +++ b/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java @@ -1,7 +1,6 @@ package org.baeldung.spring; import org.baeldung.security.MySavedRequestAwareAuthenticationSuccessHandler; -import org.springframework.beans.factory.config.MethodInvokingFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @@ -25,6 +24,7 @@ public class SecurityJavaConfig extends WebSecurityConfigurerAdapter { public SecurityJavaConfig() { super(); + SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); } // @@ -47,7 +47,7 @@ public class SecurityJavaConfig extends WebSecurityConfigurerAdapter { .antMatchers("/api/csrfAttacker*").permitAll() .antMatchers("/api/customer/**").permitAll() .antMatchers("/api/foos/**").authenticated() - .antMatchers("/api/async/**").authenticated() + .antMatchers("/api/async/**").permitAll() .and() .httpBasic() // .and() @@ -66,14 +66,5 @@ public class SecurityJavaConfig extends WebSecurityConfigurerAdapter { public SimpleUrlAuthenticationFailureHandler myFailureHandler() { return new SimpleUrlAuthenticationFailureHandler(); } - - @Bean - public MethodInvokingFactoryBean methodInvokingFactoryBean() { - MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean(); - methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class); - methodInvokingFactoryBean.setTargetMethod("setStrategyName"); - methodInvokingFactoryBean.setArguments(new String[]{SecurityContextHolder.MODE_INHERITABLETHREADLOCAL}); - return methodInvokingFactoryBean; - } } \ No newline at end of file diff --git a/spring-security-rest/src/main/java/org/baeldung/spring/WebConfig.java b/spring-security-rest/src/main/java/org/baeldung/spring/WebConfig.java index 064fd9afa9..2c5cf98153 100644 --- a/spring-security-rest/src/main/java/org/baeldung/spring/WebConfig.java +++ b/spring-security-rest/src/main/java/org/baeldung/spring/WebConfig.java @@ -3,6 +3,7 @@ package org.baeldung.spring; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; @@ -13,12 +14,13 @@ import org.springframework.web.servlet.view.InternalResourceViewResolver; @Configuration @ComponentScan("org.baeldung.web") @EnableWebMvc +@EnableAsync public class WebConfig extends WebMvcConfigurerAdapter { public WebConfig() { super(); } - + @Override public void addResourceHandlers(final ResourceHandlerRegistry registry) { registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/"); diff --git a/spring-security-rest/src/main/java/org/baeldung/web/controller/AsyncController.java b/spring-security-rest/src/main/java/org/baeldung/web/controller/AsyncController.java index 9e78a62eed..e0fdefbb88 100644 --- a/spring-security-rest/src/main/java/org/baeldung/web/controller/AsyncController.java +++ b/spring-security-rest/src/main/java/org/baeldung/web/controller/AsyncController.java @@ -2,6 +2,7 @@ package org.baeldung.web.controller; import java.util.concurrent.Callable; +import org.apache.log4j.Logger; import org.baeldung.web.service.AsyncService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.context.SecurityContextHolder; @@ -9,29 +10,30 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.multipart.MultipartFile; @Controller public class AsyncController { - + + private static final Logger log = Logger.getLogger(AsyncService.class); + @Autowired private AsyncService asyncService; - @RequestMapping(method = RequestMethod.POST, value = "/upload") - public Callable processUpload(final MultipartFile file) { - - return new Callable() { - public Boolean call() throws Exception { - // ... - return true; - } - }; - } - @RequestMapping(method = RequestMethod.GET, value = "/async") @ResponseBody - public Boolean checkIfContextPropagated() throws Exception{ - return asyncService.checkIfPrincipalPropagated().call() && asyncService.checkIfContextPropagated(SecurityContextHolder.getContext()); + public Object standardProcessing() throws Exception { + log.info("Outside the @Async logic - before the async call: " + + SecurityContextHolder.getContext().getAuthentication().getPrincipal()); + asyncService.asyncCall(); + log.info("Inside the @Async logic - after the async call: " + + SecurityContextHolder.getContext().getAuthentication().getPrincipal()); + return SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + } + + @RequestMapping(method = RequestMethod.GET, value = "/async2") + @ResponseBody + public Callable springMVCAsyncTest() { + return asyncService.checkIfPrincipalPropagated(); } } diff --git a/spring-security-rest/src/main/java/org/baeldung/web/service/AsyncService.java b/spring-security-rest/src/main/java/org/baeldung/web/service/AsyncService.java index b7cf2b9f0c..8e5a0bd510 100644 --- a/spring-security-rest/src/main/java/org/baeldung/web/service/AsyncService.java +++ b/spring-security-rest/src/main/java/org/baeldung/web/service/AsyncService.java @@ -4,8 +4,8 @@ import java.util.concurrent.Callable; public interface AsyncService { + void asyncCall(); + Callable checkIfPrincipalPropagated(); - Boolean checkIfContextPropagated(Object context); - } diff --git a/spring-security-rest/src/main/java/org/baeldung/web/service/AsyncServiceImpl.java b/spring-security-rest/src/main/java/org/baeldung/web/service/AsyncServiceImpl.java index 51f8c5157b..c3a94236f3 100644 --- a/spring-security-rest/src/main/java/org/baeldung/web/service/AsyncServiceImpl.java +++ b/spring-security-rest/src/main/java/org/baeldung/web/service/AsyncServiceImpl.java @@ -12,25 +12,25 @@ public class AsyncServiceImpl implements AsyncService { private static final Logger log = Logger.getLogger(AsyncService.class); - @Override - public Callable checkIfPrincipalPropagated() { - Object before = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - log.info("Before new thread: " + before); - return new Callable() { - public Boolean call() throws Exception { - Object after = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - log.info("New thread: " + after); - return before == after; - } - }; - } - @Async @Override - public Boolean checkIfContextPropagated(Object context) { - log.info("Before @Async: " + context); - log.info("Inside @Async: " + SecurityContextHolder.getContext()); - return context == SecurityContextHolder.getContext(); + public void asyncCall() { + log.info("Inside the @Async logic: " + SecurityContextHolder.getContext().getAuthentication().getPrincipal()); } + @Override + public Callable checkIfPrincipalPropagated() { + Object before + = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + log.info("Before new thread: " + before); + + return new Callable() { + public Boolean call() throws Exception { + Object after + = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + log.info("New thread: " + after); + return before == after; + } + }; + } } diff --git a/spring-security-rest/src/main/resources/webSecurityConfig.xml b/spring-security-rest/src/main/resources/webSecurityConfig.xml index 4172fe036f..a260460d76 100644 --- a/spring-security-rest/src/main/resources/webSecurityConfig.xml +++ b/spring-security-rest/src/main/resources/webSecurityConfig.xml @@ -34,9 +34,4 @@ - - \ No newline at end of file diff --git a/spring-security-rest/src/main/webapp/WEB-INF/web.xml b/spring-security-rest/src/main/webapp/WEB-INF/web.xml index c030a9dd63..3195603837 100644 --- a/spring-security-rest/src/main/webapp/WEB-INF/web.xml +++ b/spring-security-rest/src/main/webapp/WEB-INF/web.xml @@ -32,6 +32,7 @@ throwExceptionIfNoHandlerFound true + true api @@ -42,12 +43,13 @@ springSecurityFilterChain org.springframework.web.filter.DelegatingFilterProxy + true springSecurityFilterChain /* REQUEST - ASYNC + ASYNC diff --git a/spring-security-rest/src/test/java/org/baeldung/web/AsyncControllerTest.java b/spring-security-rest/src/test/java/org/baeldung/web/AsyncControllerTest.java index 37122ed836..054643f00c 100644 --- a/spring-security-rest/src/test/java/org/baeldung/web/AsyncControllerTest.java +++ b/spring-security-rest/src/test/java/org/baeldung/web/AsyncControllerTest.java @@ -12,7 +12,6 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mock.web.MockHttpSession; -import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @@ -42,10 +41,8 @@ public class AsyncControllerTest { } @Test - public void testProcessUpload() throws Exception { - MockMultipartFile jsonFile = new MockMultipartFile("json", "", "application/json", - "{\"json\": \"someValue\"}".getBytes()); - mockMvc.perform(MockMvcRequestBuilders.fileUpload("/upload").file(jsonFile)).andExpect(status().isOk()); + public void testAsync() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/async")).andExpect(status().is5xxServerError()); } }