로그성 데이터 저장 시 사용할 이벤트핸들러를
@EventListener에 @Async 어노테이션 추가하여 비동기로 구현하려고 하니 수정한사람이 null로 들어가는 문제 발생
(SecurityContext의 인증정보에서 유저이름을 가져와 수정자로 지정하는 구조)
Spring Security Authentication는 ThreadLocal 바인딩 이 Default
@Async를 사용하여 비동기 메서드 작성 시, 로직이 새 스레드에서 실행 되고 SpringSecurityContext의 인증정보에 접근 불가
@RequestMapping(method = RequestMethod.GET, value = "/async")
@ResponseBody
public Object standardProcessing() throws Exception {
// Before asyncCall: OK
SecurityContextHolder.getContext()
.getAuthentication()
.getPrincipal();
// Inside Of asyncCall - NPE
asyncService.asyncCall();
// After asyncCall: OK
SecurityContextHolder.getContext()
.getAuthentication()
.getPrincipal();
return SecurityContextHolder.getContext()
.getAuthentication()
.getPrincipal();
}
@Async
public void asyncCall() {
SecurityContextHolder.getContext()
.getAuthentication()
.getPrincipal();
}
비동기 스레드 내부에서 SecurityContext 의 인증정보에 액세스하려면,
@Bean
public DelegatingSecurityContextAsyncTaskExecutor taskExecutor(ThreadPoolTaskExecutor delegate) {
return new DelegatingSecurityContextAsyncTaskExecutor(delegate);
}