spring-security Spring @已调度方法SecurityContext

enyaitl3  于 2022-11-11  发布在  Spring
关注(0)|答案(1)|浏览(167)

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

ybzsozfc1#

给出的摘录永远不会起作用。

说明:

本地会话管理由底层servlet API和容器提供。HttpSession对象仅在用户在后台使用request.getSession()登录时创建,稍后SecurityContextHolder.getContext().getAuthentication();将在内部使用此HttpSession。这意味着它与用户的请求有关系,该请求是容器管理的线程,而不是运行调度程序的普通旧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.      
   }

此外,您必须在安全配置中启用sessionRegistry,首先必须侦听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();
    }
 }

有关如何获取当前登录用户see here的详细信息。

相关问题