6

我正在开发一个使用 Spring Security 作为安全层的 webapp。

对我们而言,一项重要功能是了解哪个用户正在访问该应用程序,以及他们在该应用程序上花费了多少时间。

我不确定如何处理它。是否有其他一些框架可以处理这种使用统计?

有没有办法使用 Spring Security 本身来处理它?

// 我正在阅读有关 Spring Security 的更多信息,似乎它的过滤器可以帮助我。任何进展都会在这里分享。

4

2 回答 2

6

我认为我能想到的解决方案之一是使用 HttpSessionListener,如果您实现 Session 侦听器,您可以捕获创建和销毁新用户会话的时间,您可以利用您的 Spring 安全上下文持有者来获得保留登录用户的唯一名称/用户 ID

我在想这样的事情

 public class SesssionListenerImpl implements HttpSessionListener 
 {
  @Override
  public void sessionCreated(HttpSessionEvent httpSessionEvent) 
  {
      String uniqueName =     SecurityContextHolder.getContext().getAuthentication().getName();
     String sessionId = httpSessionEvent.getSession().getId();
     long beginTimeInSeconds = System.currentTimeMillis()/1000;
//create a record and persist to data base with sessionId, uniquename, sessionBeginTime

}

@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) 
{

    SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    httpSessionEvent.getSession().getId();
    long endTime = System.currentTimeMillis()/1000;
    //load the record based on sessionId
    //update the record with sessionEndTime
}
}

话虽如此,这种方法几乎没有缺点,如果 HTTP 会话永远不会失效,那么您最终会得到一些没有结束时间的会话。

  • 如果您可以轻轻地促使您的用户群一直注销作为一种好的做法(尽管不是一个实用的解决方案)
  • 您可以做的可能是加载正文并检查用户是否离开您的域或使用窗口关闭按钮关闭窗口并触发会话无效以捕获结束时间

更新

你是对的,我认为你可以使用spring应用程序事件机制,将它添加到你的web.xml中,这个监听器发布HTTP会话事件,否则即使你实现ApplicationListener你也无法访问会话事件

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

现在添加一个实现 ApplicationListener 的新类

  @Service
 public class ApplicationSecurityListener implements ApplicationListener<ApplicationEvent>
 {
  @Override
  public void onApplicationEvent(ApplicationEvent event)
  {

    if ( event instanceof AuthorizationFailureEvent )
    {
        AuthorizationFailureEvent authorizationFailureEvent = ( AuthorizationFailureEvent ) event;
        System.out.println ( "not authorized:" + authorizationFailureEvent );
    }
    else if ( event instanceof AuthenticationFailureBadCredentialsEvent )
    {
        AuthenticationFailureBadCredentialsEvent badCredentialsEvent = ( AuthenticationFailureBadCredentialsEvent ) event;
        System.out.println ( "badCredentials:" + badCredentialsEvent );
    }
            //login success event
    else if ( event instanceof AuthenticationSuccessEvent )
    {
        AuthenticationSuccessEvent authenticationSuccessEvent = ( AuthenticationSuccessEvent ) event;
        //this will provide user id and password but no session, get source has all the user information in security context
        System.out.println ( "AuthenticationSuccessEvent:" + authenticationSuccessEvent.getSource() );
    }
    //this event will published if you add the HttpSessionEventPublisher to web.xml
    else if ( event instanceof SessionDestroyedEvent )
    {
        SessionDestroyedEvent sessinEvent = ( SessionDestroyedEvent ) event;
        System.out.println ( "SessionDestroyedEvent:" + sessinEvent.getId() );
        //load session if it is not empty
        if(sessinEvent.getSecurityContext() != null)
        {
            System.out.println ( "SessionDestroyedEvent:" + sessinEvent.getSecurityContext().getAuthentication().getName() );
            //update the session with endTime
        }
    }
    else
    {
        //System.out.println ( "undefined: " + event.getClass ().getName () );
    }


}

}

如果您想自己捕获注销还有另一个事件,您可以实现 LogoutHandler 让您可以访问 logut 事件。

于 2011-12-19T15:07:12.533 回答
-1

也许你正在寻找这样的东西:

跟踪您网站上当前用户的实用程序,以及他们详细去过的地方。这使您可以跟踪整个站点的“点击流”或“流量路径”。

http://www.quartzscheduler.org/clickstream/

于 2011-12-19T00:11:22.620 回答