Spring Boot2.x教程:(十四)Spring Security新线程为什么获取不到用户信息-续1

大家好,我是欧阳方超,微信公众号同名。在这里插入图片描述

1 概述

除了手动传递SecurityContext之外,还可以使用代理线程DelegatingSecurityContextExecutorService来执行异步任务,这样可以将父线程的securityConext传播到异步线程中。

2 创建 DelegatingSecurityContextExecutorService Bean

在基于 Spring 的应用中,我们可以创建一个DelegatingSecurityContextExecutorService的 Bean,以便在CompletableFuture中使用它来自动处理SecurityContext的传递。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.concurrent.DelegatingSecurityContextExecutorService;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Configuration
public class AsyncSecurityConfig {

    // 创建一个基础的线程池
    @Bean
    public ExecutorService baseExecutorService() {
        return Executors.newFixedThreadPool(10);
    }

    // 创建 DelegatingSecurityContextExecutorService Bean
    @Bean
    public DelegatingSecurityContextExecutorService delegatingSecurityContextExecutorService(ExecutorService baseExecutorService) {
        return new DelegatingSecurityContextExecutorService(baseExecutorService);
    }
}

在上述代码中,首先创建了一个基础的ExecutorService,这里使用了Executors.newFixedThreadPool(10)创建了一个固定大小为 10 的线程池。然后,将这个基础的线程池注入到DelegatingSecurityContextExecutorService的构造函数中,创建了DelegatingSecurityContextExecutorService Bean。这个DelegatingSecurityContextExecutorService会在每个任务执行时,自动从当前线程获取SecurityContext并设置到执行任务的线程中。

3 在 CompletableFuture 中使用 DelegatingSecurityContextExecutorService

假设有一个服务层方法,需要在异步操作中访问当前用户的信息(存储在SecurityContext中),可以这样使用CompletableFuture和DelegatingSecurityContextExecutorService:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

@Service
public class MyService {

    @Autowired
    private DelegatingSecurityContextExecutorService delegatingSecurityContextExecutorService;
    public CompletableFuture<String> doAsyncOperation() {
        
    CompletableFuture.runAsync(() -> {
    SecurityContextHolder.setContext(currentContext);
    // 在这里执行需要安全上下文的操作
}, delegatingSecurityContextExecutorService);
    }
}

在上述MyService类中,我们注入了DelegatingSecurityContextExecutorService。在doAsyncOperation方法中,我们使用CompletableFuture.supplyAsync创建了一个异步任务,并指定了DelegatingSecurityContextExecutorService作为执行器。这样,在异步任务内部,我们可以安全地获取SecurityContext并进行相应的操作,无需手动传递SecurityContext。

4 总结

通过创建DelegatingSecurityContextExecutorService Bean 并在CompletableFuture中使用它,能够优雅地解决CompletableFuture异步任务中SecurityContext的传递问题。这种自动传递机制与手动传递方式相比,大大简化了代码逻辑,减少了因手动处理不当而导致安全漏洞的风险,提高了应用的安全性和可维护性。
我是欧阳方超,把事情做好了自然就有兴趣了,如果你喜欢我的文章,欢迎点赞、转发、评论加关注。我们下次见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值