简体   繁体   English

Logout / Session超时捕获spring security

[英]Logout/Session timeout catching with spring security

I'm using spring/spring-security 3.1 and want to take some action whenever the user logs out (or if the session is timed out). 我正在使用spring / spring-security 3.1并希望在用户注销时(或者如果会话超时)采取某些操作。 I managed to get the action done for logout but for session timeout, I can't get it working. 我设法为注销完成了操作,但是对于会话超时,我无法使其正常工作。

In web.xml I only have the ContextLoaderListener specified ( can this be the issue? ) and of course the DelegatingFilterProxy. 在web.xml中我只指定了ContextLoaderListener(这可能是问题吗?),当然还有DelegatingFilterProxy。

I use the auto config like this. 我像这样使用自动配置。

    <security:http auto-config="false" use-expressions="false">
    <security:intercept-url pattern="/dialog/*"
        access="ROLE_USERS" />
    <security:intercept-url pattern="/boa/*"
        access="ROLE-USERS" />
    <security:intercept-url pattern="/*.html"
        access="ROLE-USERS" />

    <security:form-login login-page="/auth/login.html"
        default-target-url="/index.html" />
    <security:logout logout-url="/logout"
         invalidate-session="true"
        delete-cookies="JSESSIONID" success-handler-ref="logoutHandler" />
</security:http>

<bean id="logoutHandler" class="com.bla.bla.bla.LogoutHandler">
    <property name="logoutUrl" value="/auth/logout.html"/>
</bean>

The logout handler is called when user clicks logout, which will make some calls to a database. 当用户单击注销时,将调用注销处理程序,这将调用数据库。

But how do I handle the session timeout ??? 但是如何处理会话超时???

One way to handle it would be to inject the username into the session when user logs in and then use an ordinary httpsessionlistener and do the same thing on session timeout. 处理它的一种方法是在用户登录时将用户名注入会话,然后使用普通的httpsessionlistener并在会话超时时执行相同的操作。

Is there a similar way with spring security, so that when spring discovers that the session is to timeout, I can hook in there, access the Authentication and get the UserDetails from there and do the clean up. 弹簧安全性是否有类似的方式,因此当spring发现会话超时时,我可以在那里挂钩,访问Authentication并从那里获取UserDetails并进行清理。

I've got a simpler solution. 我有一个更简单的解决方案。 This works for both logout and session timeout. 这适用于注销和会话超时。

@Component
public class LogoutListener implements ApplicationListener<SessionDestroyedEvent> {

    @Override
    public void onApplicationEvent(SessionDestroyedEvent event)
    {
        List<SecurityContext> lstSecurityContext = event.getSecurityContexts();
        UserDetails ud;
        for (SecurityContext securityContext : lstSecurityContext)
        {
            ud = (UserDetails) securityContext.getAuthentication().getPrincipal();
            // ...
        }
    }

}

web.xml: web.xml中:

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

Ok, I got a solution working, it's not as good as I'd like, but it get's me to the result. 好吧,我有一个解决方案正在运行,它不如我想的那么好,但它让我得到了结果。

I create a bean from which I can get a hold of the ApplicationContext. 我创建了一个bean,我可以从中获取ApplicationContext。

public class AppCtxProvider implements ApplicationContextAware {
private static WeakReference<ApplicationContext> APP_CTX;

@Override
public void setApplicationContext(ApplicationContext applicationContext)
        throws BeansException {
    APP_CTX = new WeakReference<ApplicationContext>(applicationContext);
}

public static ApplicationContext getAppCtx() {
    return APP_CTX.get();
}
}

I implement HttpSessionEventPublisher and on destroy, i get the UserDetails via sessionRegistry.getSessionInfo(sessionId) 我实现HttpSessionEventPublisher并在销毁时,我通过sessionRegistry.getSessionInfo(sessionId)获取UserDetails

Now I have the spring beans which I need to do the cleanup of the session and the user for whom the session timed out for. 现在我有了一个spring bean,我需要对会话进行清理以及会话超时的用户。

public class SessionTimeoutHandler extends HttpSessionEventPublisher {
@Override
public void sessionCreated(HttpSessionEvent event) {
    super.sessionCreated(event);
}

@Override
public void sessionDestroyed(HttpSessionEvent event) {
    SessionRegistry sessionRegistry = getSessionRegistry();
    SessionInformation sessionInfo = (sessionRegistry != null ? sessionRegistry
            .getSessionInformation(event.getSession().getId()) : null);
    UserDetails ud = null;
    if (sessionInfo != null) {
        ud = (UserDetails) sessionInfo.getPrincipal();
    }
    if (ud != null) {
               // Do my stuff
    }
    super.sessionDestroyed(event);
}

private SessionRegistry getSessionRegistry() {
    ApplicationContext appCtx = AppCtxProvider.getAppCtx();
    return appCtx.getBean("sessionRegistry", SessionRegistry.class);
}

You can use SimpleRedirectInvalidSessionStrategy to redirect to a URL when an invalid requested session is detected by the SessionManagementFilter. 当SessionManagementFilter检测到无效的请求会话时,您可以使用SimpleRedirectInvalidSessionStrategy重定向到URL。

Sample applicationContext would be like this: 示例applicationContext将是这样的:

<http>
    <custom-filter ref="sessionManagementFilter" before="SESSION_MANAGEMENT_FILTER" />
<http>


<beans:bean id="sessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter">
    <beans:constructor-arg name="securityContextRepository" ref="httpSessionSecurityContextRepository" />
    <beans:property name="invalidSessionStrategy" ref="simpleRedirectInvalidSessionStrategy " />
</beans:bean>

<beans:bean id="simpleRedirectInvalidSessionStrategy" class="org.springframework.security.web.session.SimpleRedirectInvalidSessionStrategy">
  <beans:constructor-arg name="invalidSessionUrl" value="/general/logins/sessionExpired.jsf" />
  <beans:property name="createNewSession" value="false" />
</beans:bean>
<beans:bean id="httpSessionSecurityContextRepository" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"/>

If you are using JSF, also refer to JSF 2, Spring Security 3.x and Richfaces 4 redirect to login page on session time out for ajax requests on how to handle Ajax requests as well. 如果您正在使用JSF,请参考JSF 2,Spring Security 3.x和Richfaces 4在会话超时时重定向到登录页面,以获取有关如何处理Ajax请求的ajax请求

UPDATE : In such a case, you can extend the HttpSessionEventPublisher and listen for sessionDestroyed events like this: 更新 :在这种情况下,您可以扩展HttpSessionEventPublisher并监听sessionDestroyed事件,如下所示:

package com.examples;
import javax.servlet.http.HttpSessionEvent;

import org.springframework.security.web.session.HttpSessionEventPublisher;


public class MyHttpSessionEventPublisher extends HttpSessionEventPublisher {

   @Override
   public void sessionCreated(HttpSessionEvent event) {
      super.sessionCreated(event);
   }

   @Override
   public void sessionDestroyed(HttpSessionEvent event) {
      //do something
      super.sessionDestroyed(event);
   }

}

and then register this listener in your web.xml like this: 然后在你的web.xml中注册这个监听器,如下所示:

<listener>
    <listener-class>com.examples.MyHttpSessionEventPublisher</listener-class>
 </listener>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM