복붙노트

[SPRING] 자바의 미래 - Spring 인증은 AuditorAware에서 null입니다.

SPRING

자바의 미래 - Spring 인증은 AuditorAware에서 null입니다.

이것은 나의 시나리오이다 :

My app에는 Mongo Auditing이 활성화되어 있으며, SecurityContext에서 현재 사용자를 얻는 AuditorAware가 있습니다. 이것은 동기식 메서드에서 잘 작동하며 현재 감사자는 성공적으로 저장되지만 @Async 메서드로 제대로 작동하지는 못합니다.

내 Mongo 데이터베이스에서 일부 업데이트를 수행하는 비동기 메서드 (CompletableFuture)가 있습니다. AuditorAware.getCurrentAuditor ()가 호출되면 인증 정보가없고 현재 감사자를 가져올 수 없습니다 (SecurityContextHolder.getContext (). getAuthentication ()은 null을 반환합니다).

@Override
public User getCurrentAuditor() {
   Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

   if (authentication == null || !authentication.isAuthenticated()
                || authentication instanceof AnonymousAuthenticationToken) {
            log.error("Not authenticated");
            return null;
    }

    [...]

}

DelegatingSecurityContextAsyncTaskExecutor를 사용하고 있습니다.

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(20);
        executor.setMaxPoolSize(100);
        executor.setQueueCapacity(200);
        executor.initialize();

        return new DelegatingSecurityContextAsyncTaskExecutor(executor);
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new ItacaExceptionHandler();
    }

} 

어떻게 제대로 작동하게 할 수 있습니까?

해결법

  1. ==============================

    1.스프링 보안 컨텍스트는 항상 Threadlocal에 바인딩됩니다.

    스프링 보안 컨텍스트는 항상 Threadlocal에 바인딩됩니다.

    아마도 보안 컨텍스트에 대해 MODE_INHERITABLETHREADLOCAL을 추가로 설정할 수 있습니다.

    @Bean
    public MethodInvokingFactoryBean methodInvokingFactoryBean() {
        MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
        methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
        methodInvokingFactoryBean.setTargetMethod("setStrategyName");
        methodInvokingFactoryBean.setArguments(new String[]{SecurityContextHolder.MODE_INHERITABLETHREADLOCAL});
        return methodInvokingFactoryBean;
    }
    

    http://www.ogrigas.eu/spring/2010/04/inherit-spring-security-context-in-child-threads

    스프링 보안 SecurityContextHolder 전략을 설정하는 방법은 무엇입니까?

  2. ==============================

    2.kuhajeyan의 답변에 대한 의견에 따라 Spring @Async와 함께 CompletableFuture를 제대로 사용하지 않는 것으로 보입니다.

    kuhajeyan의 답변에 대한 의견에 따라 Spring @Async와 함께 CompletableFuture를 제대로 사용하지 않는 것으로 보입니다.

    예를 들어를 사용하여 작업을 시작하면 CompletableFuture.supplyAsync (Supplier)는 @Async에 대해 구성한 것이 아니라 공통 ForkJoinPool에 의해 실행됩니다. Executor를 인수로 사용하는 오버로드를 사용할 수는 있지만 실제로는 @Async의 이점이 없습니다.

    대신 Spring이 작업 실행을 처리하도록하고 CompletableFuture를 다음과 같이 반환하면됩니다.

    @Async
    public CompletableFuture<String> someMethod() {
        // do some computation, but return a completed future
        return CompletableFuture.completedFuture("Hello World!");
    }
    

    Spring은 메소드가 리턴 할 때 완료 될 CompletableFuture를 즉시 리턴하면서 구성된 Executor에서 비동기 적으로 메소드를 실행한다.

    Spring 4.2 이상을 사용하고 있다면, 이것은 기본적으로 지원됩니다. 그렇지 않으면 약간의 구현이 필요하지만 다른 질문이 필요합니다.

  3. from https://stackoverflow.com/questions/40345643/java-future-spring-authentication-is-null-into-auditoraware by cc-by-sa and MIT license