[SPRING] 비동기 메서드를 실행하는 사용자 가져 오기
SPRING비동기 메서드를 실행하는 사용자 가져 오기
다음과 같이 Spring을 사용하는 스프링에서 사용자를 얻으려고합니다.
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
문제는 메서드가 비동기이며 주석 @Async가있는 것입니다.
@Service
@Transactional
public class FooServiceImpl implements FooService {
@Async("asyncExecutor")
public void fooMethod(String bar) {
System.out.println("Foo: " + bar);
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
}
}
문제는 비동기 메서드가 다른 컨텍스트의 다른 스레드에서 실행된다는 점입니다. 나는 SecurityContextDelegationAsyncTaskExecutor를 사용하여 시도했다. 사용자가 비동기 메서드로 전파되지만 내가 로그 아웃하면 비동기 메서드의 사용자가 null입니다. 이것은 내 코드입니다.
@Configuration
@EnableAsync
public class SpringAsyncConfig implements AsyncConfigurer {
@Override
@Bean(name = "asyncExecutor")
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(1);
executor.setThreadGroupName("MyCustomExecutor");
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setBeanName("asyncExecutor");
executor.initialize();
return new DelegatingSecurityContextAsyncTaskExecutor(executor);
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new CustomAsyncExceptionHandler();
}
}
또한 ThreadPoolTaskExecutor를 사용하고 "MODE_INHERITABLETHREADLOCAL"을 사용하여 스프링 보안 컨텍스트를 설정했습니다. 그러나 결과는 같습니다. 응용 프로그램에 로그인 한 경우 사용자가 null이 아닙니다. 로그인하지 않으면 사용자는 null입니다. 나는 현재 로그인 한 사용자가 아니라 메소드를 실행하는 사용자를 정말로 원합니다. 내 코드 :
@Configuration
@EnableAsync
public class SpringAsyncConfig implements AsyncConfigurer {
@Override
@Bean(name = "asyncExecutor")
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(1);
executor.setThreadGroupName("MyCustomExecutor");
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setBeanName("asyncExecutor");
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new CustomAsyncExceptionHandler();
}
}
@Configuration
@ComponentScan(basePackageClasses = Application.class, includeFilters = @Filter({Controller.class}), useDefaultFilters = true)
public class MvcConfiguration extends WebMvcConfigurationSupport {
//others beans
@Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
methodInvokingFactoryBean.setTargetMethod("setStrategyName");
methodInvokingFactoryBean.setArguments(new String[]{SecurityContextHolder.MODE_INHERITABLETHREADLOCAL});
return methodInvokingFactoryBean;
}
}
마지막으로, 나는이 게시물 인 Spring Security와 @Async를 발견했다. CustomThreadPoolTaskExecutor가 execute 메소드를 오버 라이딩하려고 시도합니다. 그러나이 방법은 절대 실행되지 않습니다. 실행되는 ThreadPoolTaskExecutor의 메소드는 다음과 같습니다.
<T> Future<T> submit(Callable<T> task)
내 코드 :
@Configuration
@EnableAsync
public class SpringAsyncConfig implements AsyncConfigurer {
@Override
@Bean(name = "asyncExecutor")
public Executor getAsyncExecutor() {
CustomThreadPoolTaskExecutor executor = new CustomThreadPoolTaskExecutor();
executor.setMaxPoolSize(1);
executor.setThreadGroupName("MyCustomExecutor");
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setBeanName("asyncExecutor");
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new CustomAsyncExceptionHandler();
}
}
public class CustomThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
private static final long serialVersionUID = 1L;
@Override
public void execute(final Runnable r) {
final Authentication a = SecurityContextHolder.getContext().getAuthentication();
super.execute(new Runnable() {
@Override
public void run() {
try {
SecurityContext ctx = SecurityContextHolder.createEmptyContext();
ctx.setAuthentication(a);
SecurityContextHolder.setContext(ctx);
r.run();
} finally {
SecurityContextHolder.clearContext();
}
}
});
}
}
내 사용자 정의 실행 메소드가 실행되지 않습니다. 커스텀 ThreadPoolTaskExecutor에서 내가 뭘 잘못하고 있니? 다른 방법은 비동기 메서드를 실행하는 사용자를 얻는 것입니다. 컨텍스트의 현재 사용자가 없습니다.
해결법
-
==============================
1.아마 이것은 execute-method를 호출하는 것을 돕는다.
아마 이것은 execute-method를 호출하는 것을 돕는다.
@Override @Bean(name = "asyncExecutor") public Executor getAsyncExecutor() { CustomThreadPoolTaskExecutor executor = new CustomThreadPoolTaskExecutor(); executor.setMaxPoolSize(1); executor.setThreadGroupName("MyCustomExecutor"); executor.setWaitForTasksToCompleteOnShutdown(true); executor.setBeanName("asyncExecutor"); executor.initialize(); return new DelegatingSecurityContextAsyncTaskExecutor(executor); }
from https://stackoverflow.com/questions/37214386/get-user-that-runs-an-asynchronous-method by cc-by-sa and MIT license