我正在开发一个使用 Spring Security 作为安全层的 webapp。
我们的一项重要功能是了解哪个用户正在访问该应用程序,以及他们在该应用程序上花费了多少时间。
我不知道如何处理它。是否有其他框架可以处理这种使用统计数据?
有什么办法可以使用Spring Security本身来处理吗?
//我正在阅读有关 Spring Security 的更多信息,似乎它的过滤器可以帮助我。任何进展都会在这里分享。
最佳答案
我认为我能想到的解决方案之一是使用 HttpSessionListener,如果您实现 Session 监听器,您可以捕获创建和销毁新用户 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 session 永远不会失效,那么您最终会得到一些没有结束时间的 session 。
更新
您说得对,我认为您可以使用 spring 应用程序事件机制,将其添加到您的 web.xml,此监听器发布 HTTP session 事件,否则即使您实现 ApplicationListener,您也将无法访问 session 事件
<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 使您可以访问注销事件。
关于security - 记录登录时间和 session 持续时间 - Java - Spring Security,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8554346/