34

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>

ユーザーがログアウトをクリックすると、ログアウトハンドラーが呼び出されます。これにより、データベースが呼び出されます。

しかし、どうすればセッションタイムアウトを処理できますか?

これを処理する1つの方法は、ユーザーがログインしたときにユーザー名をセッションに挿入し、通常のhttpsessionlistenerを使用して、セッションのタイムアウト時に同じことを行うことです。

Springのセキュリティにも同様の方法があります。これにより、Springがセッションのタイムアウトを検出したときに、そこに接続して認証にアクセスし、そこからUserDetailsを取得して、クリーンアップを実行できます。

4

3 に答える 3

63

もっと簡単な解決策があります。これは、ログアウトとセッションタイムアウトの両方で機能します。

@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>
于 2013-08-08T14:20:19.900 に答える
7

わかりました。解決策が機能しました。思ったほど良くはありませんが、結果は得られました。

ApplicationContextを取得できるBeanを作成します。

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.getSessionInfo(sessionId)を介してUserDetailsを取得します

これで、セッションのクリーンアップを実行するために必要な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);
}
于 2012-08-09T11:12:45.580 に答える
4

SimpleRedirectInvalidSessionStrategyを使用して、無効な要求されたセッションがSessionManagementFilterによって検出されたときにURLにリダイレクトできます。

サンプルの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"/>

JSFを使用している場合は、JSF 2、Spring Security3.xおよびRichfaces4リダイレクトを参照してください。セッションタイムアウト時にログインページにリダイレクトされ、ajaxリクエストの処理方法も確認できます。

更新:このような場合、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>
于 2012-08-08T01:54:18.407 に答える