spring-security 使用Spring安全性捕获注销/会话超时

gupuwyp2  于 2022-11-11  发布在  Spring
关注(0)|答案(4)|浏览(197)

我正在使用spring/spring-security 3.1,并且希望在用户注销时(或者会话超时时)执行一些操作。我设法完成了注销操作,但是对于会话超时,我无法让它工作。
在web.xml中,我只指定了ContextLoaderListener(这是问题所在吗?),当然还有DelegatingFilterProxy。
我这样使用自动配置。

<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>

当用户单击注销时,将调用注销处理程序,这将对数据库进行一些调用。
但是如何处理会话超时???
处理它的一种方法是在用户登录时将用户名注入到会话中,然后使用普通的httpsessionlistener,并在会话超时时执行相同的操作。
Spring Security 是否也有类似的方法,以便当spring发现会话将要超时时,我可以在那里挂钩,访问Authentication并从那里获取UserDetails,然后进行清理。

xkrw2x1b

xkrw2x1b1#

我有一个更简单的解决方案,它对注销和会话超时都有效。

@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:

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

dojqjjoe2#

好的,我有一个解决方案,它没有我想的那么好,但它让我得到了结果。
我创建了一个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();
}
}

我实现了HttpSessionEventPublisher,并且在销毁时,我通过sessionRegistry获取用户详细信息。
现在我有了需要清理会话的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);
}
zsohkypk

zsohkypk3#

当SessionManagementFilter侦测到无效的要求阶段作业时,您可以使用SimpleRedirectInvalidSessionStrategy重新导向至URL。
示例应用程序上下文如下所示:

<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"/>

如果您使用的是JSF,也可以参考JSF 2、Spring Security 3.x和Richfaces 4,在 AJAX 请求会话超时时重定向到登录页面,了解如何处理Ajax请求。

UPDATE:在这种情况下,您可以扩展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);
   }

}

然后在web.xml中注册这个侦听器,如下所示:

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

gev0vcfq4#

假设在一个微服务应用程序创建会话时将setMaxInactive间隔设置为60秒。会话在60秒后超时,但在使用您建议的更改后,它应进入sessionDestroyed事件,但它仍处于会话创建状态,并且会话不会再次失效。

相关问题