获取运行异步方法的用户 [英] Get user that runs an asynchronous method

查看:166
本文介绍了获取运行异步方法的用户的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从应用程序spring的spring上下文中吸引用户,如下所示:

I'm trying to get the user from spring context in an application spring as follows:

Authentication auth = SecurityContextHolder.getContext().getAuthentication();

问题在于方法是异步的,带有注释@Async:

The problem is that the methods are asynchronous, with annotation @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.这是我的代码:

The problem is that the asynchronous method runs in another thread in another context. I have tried using a SecurityContextDelegationAsyncTaskExecutor. The user is propagated to the asynchronous method but if I logout, the user in the asynchronous method is null. This is my code:

@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.我真的希望运行该方法的用户,而不是当前登录的用户.我的代码:

I have also used a ThreadPoolTaskExecutor and setting the context of spring security with "MODE_INHERITABLETHREADLOCAL". But the result is the same. The user is not null if I am logged into the application. If I'm not logged the user is null. I really want the user that runs the method, not the current user logged. My code:

@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;
    }
}

最后,我找到了帖子.我尝试使用CustomThreadPoolTask​​Executor覆盖执行方法.但是这种方法永远不会运行.运行的ThreadPoolTask​​Executor方法是:

Finally, I found this post . I try with a CustomThreadPoolTaskExecutor overriding execute method. But this method never runs. The method of ThreadPoolTaskExecutor that run is:

<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();
                }
            }
        });
    }
}

我的自定义executes方法永远不会运行. 在自定义ThreadPoolTask​​Executor中我在做什么错?获取运行异步方法的用户的其他方法.没有上下文的当前用户.

My custom executes method never run. What am I doing wrong in the Custom ThreadPoolTaskExecutor? Some other way to get the user that runs an asynchronous method. No the current user of context.

推荐答案

也许这有助于调用执行方法(在我的情况下有效):

Maybe this helps to get execute-method called (worked in my case):

@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);
}

这篇关于获取运行异步方法的用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆