使用SpringSecurity处理超时

时间:2016-05-12 23:13:02

标签: spring session spring-security timeout logout

我们正在使用Spring Security来保护Web应用程序,我们希望记录登录/注销/超时事件。

请让我解释一下到目前为止的实施情况:

  1. 处理LogOut:
  2. 我们使用java配置和登录/注销工作正常,我们使用logoutSuccessHandler()捕获logout事件和会话详细信息,如username。但是,这仅在单击注销链接时有效,但在超时发生时不起作用。

    在配置类中:

    .and().formLogin().loginPage("/login").permitAll() 
           .and().logout().permitAll().logoutSuccessHandler(customLogoutSuccessHandler);
    

    和处理程序定义:

    @Component
    public class LogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
    
        @Override
        public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
                throws IOException, ServletException {
            if (authentication != null) {
                System.out.println("This user is closing the session: " + authentication.getName());
            }
            super.onLogoutSuccess(request, response, authentication);
        }
    }
    

    到目前为止登录和注销非常好,当我们点击注销链接时,我们可以拦截事件并打印用户名。让我们看看超时配置......

    1. 处理超时
    2. 要通过超时实现会话到期,我们在附加到ServletContext的侦听器中配置它:

      public class SessionListener implements HttpSessionListener {
      
          @Override
          public void sessionCreated(HttpSessionEvent event) {
              System.out.println("session created");
              event.getSession().setMaxInactiveInterval(15);
          }
      
          @Override
          public void sessionDestroyed(HttpSessionEvent event) {
             System.out.println("session destroyed");
          }
      }
      

      然后在初始化程序中:

      @Override
      public void onStartup(ServletContext servletContext) throws ServletException {
          super.onStartup(servletContext);
          servletContext.addListener(new SessionListener());
      }
      

      使用上面的代码,我们可以截取sessionDestroyed()方法中的超时,但此时HttpSessionEvent与spring会话完全无关(例如,无法访问用户名)。

      我确信我们错过了将HttpSession与Spring联系起来的东西。在我看来,我们的会话到期配置与Spring没有任何关系。

      话虽如此,我有一些问题:

      1. 有没有更好的方法来处理Spring的会话(例如会话超时),所以我们不必在ServletContext中创建一个监听器?
      2. 我们如何拦截超时并能够打印类似“Authentication.getName()”的用户详细信息?
      3. 欢迎任何建议或推荐的讲座!

        谢谢,祝你有个美好的一天!

2 个答案:

答案 0 :(得分:0)

以下是一些替代方法:

1)使用jquery超时,您可以找到更多免费插件,以便与您的网站一起使用。 (例如:jquery idle timeout

2)有一次,我也在努力解决这个问题,我一直在做的一个解决方法是使用沙盒iframe。显示页面和页面末尾的所有详细信息,将具有链接的iframe放入用户注销。

这是一些建议。

答案 1 :(得分:0)

以下是我在超时时获取用户名的方法:

@Override
public void sessionDestroyed(HttpSessionEvent event) {
    HttpSession httpSession = event.getSession();
    long lastAccessedTime = httpSession.getLastAccessedTime();
    int maxInactiveTime = httpSession.getMaxInactiveInterval() * 1000; //millis
    long currentTime = System.currentTimeMillis();
        if ((currentTime - lastAccessedTime) >= maxInactiveTime ){
        //if is a timeout
            SessionInformation i = sessionRegistry().getSessionInformation(event.getSession().getId());
            String username = ((User) i.getPrincipal()).getUsername();
        }
    }

我在同一个档案中

@Bean
public SessionRegistry sessionRegistry() {
    return new SessionRegistryImpl();
}