简体   繁体   English

Spring @Scheduled 方法 SecurityContext

[英]Spring @Scheduled method SecurityContext

Is @Scheduled annotated method out of any SecurityContext ? @Scheduled注释方法是否来自任何SecurityContext When I try to use the following it always has securitycontext/auth as null.当我尝试使用以下内容时,它总是将securitycontext/auth设置为 null。 If this is not possible then what could be the right way to run user specific authentication aware scheduled task?如果这是不可能的,那么运行用户特定身份验证感知计划任务的正确方法是什么?

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

Given excerpt will never work.鉴于摘录永远不会奏效。

Explanation:解释:

Native session management is provided by underlying servlet API and container.原生 session 管理由底层 servlet API 和容器提供。 HttpSession object is only created when the user logs in using request.getSession() under the hood and later this HttpSession will be used by SecurityContextHolder.getContext().getAuthentication(); HttpSession object 仅在用户在后台使用request.getSession()登录时创建,稍后此HttpSession将由SecurityContextHolder.getContext().getAuthentication(); internally.内部。 This means it has a relation with the user's request which is a container-managed thread, not plain old JVM thread on which your scheduler will run.这意味着它与用户的请求有关,这是一个容器管理的线程,而不是运行调度程序的普通旧 JVM 线程。

Here your scheduler does have any dependency on the user it will run independently on JVM managed thread.在这里,您的调度程序确实对用户有任何依赖性,它将在 JVM 托管线程上独立运行。 So no HttpRequest/HttpSession object will be created at all.所以根本不会创建HttpRequest/HttpSession object。

Imagine the very first time when you start the application and no user yet logged in then what would be scenario here.想象一下,当您第一次启动应用程序并且还没有用户登录时,这里会发生什么情况。

So you will always get securitycontext/auth as null only.因此,您将始终只获得 null 的securitycontext/auth

To answer your question回答你的问题

If this is not possible then what could be the right way to run user specific authentication aware scheduled task?如果这是不可能的,那么运行用户特定身份验证感知计划任务的正确方法是什么?

One way I can think of right now is, Use of spring provided SessionRegistry .我现在能想到的一种方法是,使用 spring 提供SessionRegistry It keeps track of all currently logged-in users.它跟踪所有当前登录的用户。

So you can pass this SessionRegistry object by autowiring to this scheduler and get list of all principal/logged-in users and send them a notification.因此,您可以通过自动装配到此调度程序来传递此SessionRegistry object 并获取所有主体/登录用户的列表并向他们发送通知。

Something like below -像下面的东西 -

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

Also, you have to enable sessionRegistry in your security config first you have to listen to HTTP sessions and then configure registry in your security config.此外,您必须首先在安全配置中启用 sessionRegistry,您必须先收听 HTTP 会话,然后在安全配置中配置注册表。

        public class AppInitializer implements WebApplicationInitializer {

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

and security config -和安全配置 -

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

For more details of how to get current logged in users see here .有关如何获取当前登录用户的更多详细信息, 请参见此处

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM