Skip to content

Commit 4018d45

Browse files
authored
SecurityContextHolder + @async fixes and improvements (eugenp#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
1 parent 7844b1d commit 4018d45

File tree

8 files changed

+44
-55
lines changed

8 files changed

+44
-55
lines changed

spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package org.baeldung.spring;
22

33
import org.baeldung.security.MySavedRequestAwareAuthenticationSuccessHandler;
4-
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
54
import org.springframework.context.annotation.Bean;
65
import org.springframework.context.annotation.ComponentScan;
76
import org.springframework.context.annotation.Configuration;
@@ -25,6 +24,7 @@ public class SecurityJavaConfig extends WebSecurityConfigurerAdapter {
2524

2625
public SecurityJavaConfig() {
2726
super();
27+
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
2828
}
2929

3030
//
@@ -47,7 +47,7 @@ protected void configure(final HttpSecurity http) throws Exception {// @formatte
4747
.antMatchers("/api/csrfAttacker*").permitAll()
4848
.antMatchers("/api/customer/**").permitAll()
4949
.antMatchers("/api/foos/**").authenticated()
50-
.antMatchers("/api/async/**").authenticated()
50+
.antMatchers("/api/async/**").permitAll()
5151
.and()
5252
.httpBasic()
5353
// .and()
@@ -66,14 +66,5 @@ public MySavedRequestAwareAuthenticationSuccessHandler mySuccessHandler() {
6666
public SimpleUrlAuthenticationFailureHandler myFailureHandler() {
6767
return new SimpleUrlAuthenticationFailureHandler();
6868
}
69-
70-
@Bean
71-
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
72-
MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
73-
methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
74-
methodInvokingFactoryBean.setTargetMethod("setStrategyName");
75-
methodInvokingFactoryBean.setArguments(new String[]{SecurityContextHolder.MODE_INHERITABLETHREADLOCAL});
76-
return methodInvokingFactoryBean;
77-
}
7869

7970
}

spring-security-rest/src/main/java/org/baeldung/spring/WebConfig.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.springframework.context.annotation.Bean;
44
import org.springframework.context.annotation.ComponentScan;
55
import org.springframework.context.annotation.Configuration;
6+
import org.springframework.scheduling.annotation.EnableAsync;
67
import org.springframework.web.servlet.ViewResolver;
78
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
89
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
@@ -13,12 +14,13 @@
1314
@Configuration
1415
@ComponentScan("org.baeldung.web")
1516
@EnableWebMvc
17+
@EnableAsync
1618
public class WebConfig extends WebMvcConfigurerAdapter {
1719

1820
public WebConfig() {
1921
super();
2022
}
21-
23+
2224
@Override
2325
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
2426
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");

spring-security-rest/src/main/java/org/baeldung/web/controller/AsyncController.java

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,38 @@
22

33
import java.util.concurrent.Callable;
44

5+
import org.apache.log4j.Logger;
56
import org.baeldung.web.service.AsyncService;
67
import org.springframework.beans.factory.annotation.Autowired;
78
import org.springframework.security.core.context.SecurityContextHolder;
89
import org.springframework.stereotype.Controller;
910
import org.springframework.web.bind.annotation.RequestMapping;
1011
import org.springframework.web.bind.annotation.RequestMethod;
1112
import org.springframework.web.bind.annotation.ResponseBody;
12-
import org.springframework.web.multipart.MultipartFile;
1313

1414
@Controller
1515
public class AsyncController {
16-
16+
17+
private static final Logger log = Logger.getLogger(AsyncService.class);
18+
1719
@Autowired
1820
private AsyncService asyncService;
1921

20-
@RequestMapping(method = RequestMethod.POST, value = "/upload")
21-
public Callable<Boolean> processUpload(final MultipartFile file) {
22-
23-
return new Callable<Boolean>() {
24-
public Boolean call() throws Exception {
25-
// ...
26-
return true;
27-
}
28-
};
22+
@RequestMapping(method = RequestMethod.GET, value = "/async")
23+
@ResponseBody
24+
public Object standardProcessing() throws Exception {
25+
log.info("Outside the @Async logic - before the async call: "
26+
+ SecurityContextHolder.getContext().getAuthentication().getPrincipal());
27+
asyncService.asyncCall();
28+
log.info("Inside the @Async logic - after the async call: "
29+
+ SecurityContextHolder.getContext().getAuthentication().getPrincipal());
30+
return SecurityContextHolder.getContext().getAuthentication().getPrincipal();
2931
}
3032

31-
@RequestMapping(method = RequestMethod.GET, value = "/async")
33+
@RequestMapping(method = RequestMethod.GET, value = "/async2")
3234
@ResponseBody
33-
public Boolean checkIfContextPropagated() throws Exception{
34-
return asyncService.checkIfPrincipalPropagated().call() && asyncService.checkIfContextPropagated(SecurityContextHolder.getContext());
35+
public Callable<Boolean> springMVCAsyncTest() {
36+
return asyncService.checkIfPrincipalPropagated();
3537
}
3638

3739
}

spring-security-rest/src/main/java/org/baeldung/web/service/AsyncService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
public interface AsyncService {
66

7+
void asyncCall();
8+
79
Callable<Boolean> checkIfPrincipalPropagated();
810

9-
Boolean checkIfContextPropagated(Object context);
10-
1111
}

spring-security-rest/src/main/java/org/baeldung/web/service/AsyncServiceImpl.java

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,25 @@ public class AsyncServiceImpl implements AsyncService {
1212

1313
private static final Logger log = Logger.getLogger(AsyncService.class);
1414

15+
@Async
1516
@Override
16-
public Callable<Boolean> checkIfPrincipalPropagated() {
17-
Object before = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
18-
log.info("Before new thread: " + before);
19-
return new Callable<Boolean>() {
20-
public Boolean call() throws Exception {
21-
Object after = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
22-
log.info("New thread: " + after);
23-
return before == after;
24-
}
25-
};
17+
public void asyncCall() {
18+
log.info("Inside the @Async logic: " + SecurityContextHolder.getContext().getAuthentication().getPrincipal());
2619
}
2720

28-
@Async
2921
@Override
30-
public Boolean checkIfContextPropagated(Object context) {
31-
log.info("Before @Async: " + context);
32-
log.info("Inside @Async: " + SecurityContextHolder.getContext());
33-
return context == SecurityContextHolder.getContext();
34-
}
22+
public Callable<Boolean> checkIfPrincipalPropagated() {
23+
Object before
24+
= SecurityContextHolder.getContext().getAuthentication().getPrincipal();
25+
log.info("Before new thread: " + before);
3526

27+
return new Callable<Boolean>() {
28+
public Boolean call() throws Exception {
29+
Object after
30+
= SecurityContextHolder.getContext().getAuthentication().getPrincipal();
31+
log.info("New thread: " + after);
32+
return before == after;
33+
}
34+
};
35+
}
3636
}

spring-security-rest/src/main/resources/webSecurityConfig.xml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,4 @@
3434
</authentication-provider>
3535
</authentication-manager>
3636

37-
<beans:bean
38-
class="org.springframework.beans.factory.config.MethodInvoki‌​ngFactoryBean"
39-
p:targetClass="org.springframework.security.core.context.Sec‌​urityContextHolder"
40-
p:targetMethod="setStrategyName" p:arguments="MODE_INHERITABLETHREADLOCAL" />
41-
4237
</beans:beans>

spring-security-rest/src/main/webapp/WEB-INF/web.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
<param-name>throwExceptionIfNoHandlerFound</param-name>
3333
<param-value>true</param-value>
3434
</init-param>
35+
<async-supported>true</async-supported>
3536
</servlet>
3637
<servlet-mapping>
3738
<servlet-name>api</servlet-name>
@@ -42,12 +43,13 @@
4243
<filter>
4344
<filter-name>springSecurityFilterChain</filter-name>
4445
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
46+
<async-supported>true</async-supported>
4547
</filter>
4648
<filter-mapping>
4749
<filter-name>springSecurityFilterChain</filter-name>
4850
<url-pattern>/*</url-pattern>
4951
<dispatcher>REQUEST</dispatcher>
50-
<dispatcher>ASYNC</dispatcher>
52+
<dispatcher>ASYNC</dispatcher>
5153
</filter-mapping>
5254

5355
<!-- <welcome-file-list> -->

spring-security-rest/src/test/java/org/baeldung/web/AsyncControllerTest.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import org.mockito.Mock;
1313
import org.springframework.beans.factory.annotation.Autowired;
1414
import org.springframework.mock.web.MockHttpSession;
15-
import org.springframework.mock.web.MockMultipartFile;
1615
import org.springframework.test.context.ContextConfiguration;
1716
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
1817
import org.springframework.test.context.web.WebAppConfiguration;
@@ -42,10 +41,8 @@ public void setup() {
4241
}
4342

4443
@Test
45-
public void testProcessUpload() throws Exception {
46-
MockMultipartFile jsonFile = new MockMultipartFile("json", "", "application/json",
47-
"{\"json\": \"someValue\"}".getBytes());
48-
mockMvc.perform(MockMvcRequestBuilders.fileUpload("/upload").file(jsonFile)).andExpect(status().isOk());
44+
public void testAsync() throws Exception {
45+
mockMvc.perform(MockMvcRequestBuilders.get("/async")).andExpect(status().is5xxServerError());
4946
}
5047

5148
}

0 commit comments

Comments
 (0)