Spring @Scheduled方法SecurityContext

问题描述 投票:1回答:1

@Scheduled 注解方法中的任何 SecurityContext? 当我尝试使用下面的内容时,它总是有 securitycontext/auth 为空。如果这是不可能的,那么有什么正确的方法来运行用户特定的认证意识的预定任务呢?

    @Scheduled(fixedDelay = 10000)
    // This method will send notifications to the current user
    public void sendUserNotifications() {
        SecurityContext sc = SecurityContextHolder.getContext();
        Authentication auth = sc.getAuthentication();

        if(auth == null) {

            log.info(">> SecurityContext=[{}], Authentication[auth] is {}, please login to receive notifications", sc, auth);

            return;
        }
java spring spring-security spring-scheduled spring-context
1个回答
0
投票

给定的摘录将永远不会工作。

解释。

原生会话管理由底层servlet API和容器提供。HttpSession 只有当用户使用以下方式登录时,才会创建一个对象 request.getSession() 引擎盖下 HttpSession 将由 SecurityContextHolder.getContext().getAuthentication(); 内部。 这意味着它与用户的请求有关系,而用户的请求是一个容器管理的线程,而不是普通的JVM线程,你的调度器将在其上运行。

在这里,你的调度器对用户有任何依赖性,它将在JVM管理的线程上独立运行。所以没有 HttpRequest/HttpSession 对象将被创建。

想象一下,当你第一次启动应用程序时,还没有用户登录,那么这里会是什么情况。

所以,你总是会得到 securitycontext/auth 只作为空。

回答你的问题

如果这是不可能的,那么有什么正确的方法来运行用户特定的身份验证感知计划任务呢?

我现在能想到的一个方法是,使用spring提供的 SessionRegistry. 它可以跟踪所有当前登录的用户。

所以你可以通过这个 SessionRegistry 对象,通过自动连接到这个调度器,并获取所有主要登录用户的列表,并向他们发送通知。

就像下面这样

    @EnableScheduling
    @Component
    public class MyScheduler { 

    @Autowired
    @Qualifier("sessionRegistry")
    private SessionRegistry sessionRegistry;
    @Scheduled(fixedDelay = 10000)
    // This method will send notifications to the current user
    public void sendUserNotifications() {
    List<UserDetails> principals = sessionRegistry.getAllPrincipals()
        .stream()
        .filter(principal -> principal instanceof UserDetails)
        .map(UserDetails.class::cast)
        .collect(Collectors.toList());

    // send notification to all users.      
   }

此外,你必须在你的安全配置中启用会话注册表,首先你必须监听HTTP会话,然后在你的安全配置中配置注册表。

        public class AppInitializer implements WebApplicationInitializer {

        @Override
        public void onStartup(ServletContext servletContext) {
        ...
        servletContext.addListener(HttpSessionEventPublisher.class);
         }
        }

和安全配置 -

 @Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        // ...
        http.sessionManagement().maxSession(1).sessionRegistry(sessionRegistry());
    }

    @Bean
    public SessionRegistry sessionRegistry() {
        return new SessionRegistryImpl();
    }

    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }
 }

更多关于如何获得当前登录用户的详细信息 见此.

希望能帮到你

© www.soinside.com 2019 - 2024. All rights reserved.