@Async and SecurityContext (#872)

* @Async and Spring Security

* @Async with SecurityContext propagated

* Spring and @Async

* Simulated Annealing algorithm

* Rebase

* Rebase
This commit is contained in:
maibin 2016-12-16 10:14:48 +01:00 committed by GitHub
parent 0087a4ab3b
commit 8844871e2b
6 changed files with 126 additions and 31 deletions

View File

@ -0,0 +1,13 @@
package com.baeldung.algorithms;
import org.junit.Assert;
import org.junit.Test;
public class SimulatedAnnealingTest {
@Test
public void testSimulateAnnealing() {
Assert.assertTrue(SimulatedAnnealing.simulateAnnealing(10, 1000, 0.9) > 0);
}
}

View File

@ -1,8 +1,7 @@
package org.baeldung.spring; package org.baeldung.spring;
import org.baeldung.security.MySavedRequestAwareAuthenticationSuccessHandler; import org.baeldung.security.MySavedRequestAwareAuthenticationSuccessHandler;
import org.baeldung.security.RestAuthenticationEntryPoint; import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -10,6 +9,7 @@ import org.springframework.security.config.annotation.authentication.builders.Au
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
@Configuration @Configuration
@ -17,11 +17,11 @@ import org.springframework.security.web.authentication.SimpleUrlAuthenticationFa
@ComponentScan("org.baeldung.security") @ComponentScan("org.baeldung.security")
public class SecurityJavaConfig extends WebSecurityConfigurerAdapter { public class SecurityJavaConfig extends WebSecurityConfigurerAdapter {
@Autowired // @Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint; // private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
@Autowired // @Autowired
private MySavedRequestAwareAuthenticationSuccessHandler authenticationSuccessHandler; // private MySavedRequestAwareAuthenticationSuccessHandler authenticationSuccessHandler;
public SecurityJavaConfig() { public SecurityJavaConfig() {
super(); super();
@ -38,17 +38,21 @@ public class SecurityJavaConfig extends WebSecurityConfigurerAdapter {
protected void configure(final HttpSecurity http) throws Exception {// @formatter:off protected void configure(final HttpSecurity http) throws Exception {// @formatter:off
http http
.csrf().disable() .csrf().disable()
.authorizeRequests()
.and()
.exceptionHandling() .exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint) // .authenticationEntryPoint(restAuthenticationEntryPoint)
.and() .and()
.authorizeRequests() .authorizeRequests()
.antMatchers("/api/csrfAttacker*").permitAll() .antMatchers("/api/csrfAttacker*").permitAll()
.antMatchers("/api/customer/**").permitAll() .antMatchers("/api/customer/**").permitAll()
.antMatchers("/api/foos/**").authenticated() .antMatchers("/api/foos/**").authenticated()
.antMatchers("/api/async/**").authenticated()
.and() .and()
.formLogin() .httpBasic()
.successHandler(authenticationSuccessHandler) // .and()
.failureHandler(new SimpleUrlAuthenticationFailureHandler()) // .successHandler(authenticationSuccessHandler)
// .failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and() .and()
.logout(); .logout();
} // @formatter:on } // @formatter:on
@ -63,4 +67,13 @@ public class SecurityJavaConfig extends WebSecurityConfigurerAdapter {
return new SimpleUrlAuthenticationFailureHandler(); 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;
}
} }

View File

@ -2,14 +2,21 @@ package org.baeldung.web.controller;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import org.baeldung.web.service.AsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@Controller @Controller
public class AsyncController { public class AsyncController {
@Autowired
private AsyncService asyncService;
@RequestMapping(method = RequestMethod.POST, value = "/upload") @RequestMapping(method = RequestMethod.POST, value = "/upload")
public Callable<Boolean> processUpload(final MultipartFile file) { public Callable<Boolean> processUpload(final MultipartFile file) {
@ -21,4 +28,10 @@ public class AsyncController {
}; };
} }
@RequestMapping(method = RequestMethod.GET, value = "/async")
@ResponseBody
public Boolean checkIfContextPropagated() throws Exception{
return asyncService.checkIfPrincipalPropagated().call() && asyncService.checkIfContextPropagated(SecurityContextHolder.getContext());
}
} }

View File

@ -0,0 +1,11 @@
package org.baeldung.web.service;
import java.util.concurrent.Callable;
public interface AsyncService {
Callable<Boolean> checkIfPrincipalPropagated();
Boolean checkIfContextPropagated(Object context);
}

View File

@ -0,0 +1,36 @@
package org.baeldung.web.service;
import java.util.concurrent.Callable;
import org.apache.log4j.Logger;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
@Service
public class AsyncServiceImpl implements AsyncService {
private static final Logger log = Logger.getLogger(AsyncService.class);
@Override
public Callable<Boolean> checkIfPrincipalPropagated() {
Object before = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
log.info("Before new thread: " + before);
return new Callable<Boolean>() {
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();
}
}

View File

@ -1,33 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" <beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:sec="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation=" xmlns:sec="http://www.springframework.org/schema/security"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/security http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.2.xsd http://www.springframework.org/schema/security/spring-security-4.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd" http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
>
<http use-expressions="true" entry-point-ref="restAuthenticationEntryPoint"> <http use-expressions="true" entry-point-ref="restAuthenticationEntryPoint">
<intercept-url pattern="/api/**" access="isAuthenticated()"/> <intercept-url pattern="/api/**" access="isAuthenticated()" />
<csrf disabled="true"/> <csrf disabled="true" />
<form-login authentication-success-handler-ref="mySuccessHandler" authentication-failure-handler-ref="myFailureHandler"/> <form-login authentication-success-handler-ref="mySuccessHandler"
authentication-failure-handler-ref="myFailureHandler" />
<logout/> <logout />
</http> </http>
<beans:bean id="mySuccessHandler" class="org.baeldung.security.MySavedRequestAwareAuthenticationSuccessHandler"/> <beans:bean id="mySuccessHandler"
<beans:bean id="myFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"/> class="org.baeldung.security.MySavedRequestAwareAuthenticationSuccessHandler" />
<beans:bean id="myFailureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler" />
<authentication-manager alias="authenticationManager"> <authentication-manager alias="authenticationManager">
<authentication-provider> <authentication-provider>
<user-service> <user-service>
<user name="temporary" password="temporary" authorities="ROLE_ADMIN"/> <user name="temporary" password="temporary" authorities="ROLE_ADMIN" />
<user name="user" password="userPass" authorities="ROLE_USER"/> <user name="user" password="userPass" authorities="ROLE_USER" />
</user-service> </user-service>
</authentication-provider> </authentication-provider>
</authentication-manager> </authentication-manager>
<beans:bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"
p:targetClass="org.springframework.security.core.context.SecurityContextHolder"
p:targetMethod="setStrategyName" p:arguments="MODE_INHERITABLETHREADLOCAL" />
</beans:beans> </beans:beans>