Spring Security中的在线/离线状态

时间:2013-12-10 08:53:57

标签: spring-security

在我的网络应用程序中,我需要知道用户是在线还是离线。我需要在创建或销毁用户会话时更新数据库中的状态,因此SessionRegistry不是一个选项。

我使用会话计数器实现它 - 当用户登录时,他的计数器递增,当他退出或他的会话超时时,他的计数器减少。

的web.xml

<listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>

服务

@Service
public class UsersLoginLogoutListener implements ApplicationListener<ApplicationEvent> {

    @Autowired
    private AccountService accountService;

    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof InteractiveAuthenticationSuccessEvent) { // User log in
            System.out.println("User logged in...");
            InteractiveAuthenticationSuccessEvent iasEvent = (InteractiveAuthenticationSuccessEvent) event;
            String userName = iasEvent.getAuthentication().getName();
            if (userName != null) {
                System.out.println("...username is " + userName + ".");
                accountService.incrementSessionCounter(userName);
            }
        }
        else if (event instanceof SessionDestroyedEvent) { // User log out / session timeout
            System.out.println("User logged out or session timeout...");
            SessionDestroyedEvent sdEvent = (SessionDestroyedEvent) event;
            List<SecurityContext> lstSecurityContext = sdEvent.getSecurityContexts();
            System.out.println("...SecurityContexts list size: " + lstSecurityContext.size() + "...");
            for (SecurityContext securityContext : lstSecurityContext)
            {
                String userName = securityContext.getAuthentication().getName();
                if (userName != null) {
                    System.out.println("...username is " + userName + ".");
                    accountService.decrementSessionCounter(userName);
                }
            }
        }
    }
}
直到最近,当我注意到一个计数器增加但从未减少时,它一直工作得很好。感谢日志,我能够重现它。

用户在两个浏览器选项卡中打开登录页面并在一个选项卡上登录,然后他登录另一个选项卡而不登出第一个选项卡。如果他输入了正确的凭证,一切正常:

  

用户登录... ...用户名是testuser。

     

用户注销或会话超时...... ... SecurityContexts列表大小:   1 ......用户名是testuser。

     

用户登录... ...用户名是testuser。

即使他使用相同的浏览器登录两次,他的第一个会话也被销毁,我的计数器正常工作。 但如果他输入了错误的凭据,我会看到以下输出:

  

用户登录... ...用户名是testuser。

     

(会话超时后)

     

用户注销或会话超时...... ... SecurityContexts列表大小:   0 ...

正如您所看到的,在这种情况下,SessionDestroyedEvent被触发,但仅在会话超时和SecurityContexts列表为空之后,因此用户的会话计数器未递减。

0 个答案:

没有答案