3

Wildfly 8.1 で Java 1.7 を実行するアプリケーション3.2.5-RELEASEを使用する Spring Security で、次のシナリオを解決する必要があります。Spring Core 4.1.2-RELEASE

  1. ユーザー「bob」がログインします
  2. 管理者は「bob」を削除します
  3. 「ボブ」がログアウトすると、ログインできなくなりますが、現在のセッションはアクティブなままです。
  4. 「ボブ」を追い出したい

    //this doesn't work
    for (final SessionInformation session :    sessionRegistry.getAllSessions(user, true)) {
             session.expireNow();
    }
    
4

2 に答える 2

3
  1. アプリケーションイベントリスナーを追加して追跡HttpSessionCreatedEventHttpSessionDestroyedEventApplicationListenerHttoSession への SessionId のキャッシュを維持します。
  2. (オプション) 独自の ApplicationEvent クラスを追加しますAskToExpireSessionEvent-
  3. ユーザー管理サービスで依存関係をSessionRegistryandに追加ApplicationEventPublisherして、現在アクティブなユーザーセッションを一覧表示し、探しているユーザー、つまり「bob」に対してアクティブなセッション (多数ある可能性があるため) を見つけることができるようにします。
  4. ユーザーディスパッチを削除するAskToExpireSessionEventと、セッションごとに。
  5. 弱参照 HashMap を使用してセッションを追跡する

ユーザーサービス:

     @Service
     public class UserServiceImpl implements UserService {

      /** {@link SessionRegistry} does not exists in unit tests */
      @Autowired(required = false)
      private Set<SessionRegistry> sessionRegistries;


      @Autowired
      private ApplicationEventPublisher publisher;


     /**
      * destroys all active sessions.
      * @return <code>true</code> if any session was invalidated^
      * @throws IllegalArgumentException
      */
      @Override
      public boolean invalidateUserByUserName(final String userName) {
              if(null == StringUtils.trimToNull(userName)) {
                      throw new IllegalArgumentException("userName must not be null or empty");
              }
              boolean expieredAtLeastOneSession = false;
              for (final SessionRegistry sessionRegistry : safe(sessionRegistries)) {
                      findPrincipal: for (final Object principal : sessionRegistry.getAllPrincipals()) {
                              if(principal instanceof IAuthenticatedUser) {
                                      final IAuthenticatedUser user = (IAuthenticatedUser) principal;
                                      if(userName.equals(user.getUsername())) {
                                              for (final SessionInformation session : sessionRegistry.getAllSessions(user, true)) {
                                                      session.expireNow();
                                                      sessionRegistry.removeSessionInformation(session.getSessionId());
                                                      publisher.publishEvent(AskToExpireSessionEvent.of(session.getSessionId()));
                                                      expieredAtLeastOneSession = true;
                                              }
                                              break findPrincipal;
                                      }
                              } else {
                                      logger.warn("encountered a session for a none user object {} while invalidating '{}' " , principal, userName);
                              }
                      }
              }
              return expieredAtLeastOneSession;
      }

     }

応募イベント:

     import org.springframework.context.ApplicationEvent;

     public class AskToExpireSessionEvent extends ApplicationEvent {

             private static final long serialVersionUID = -1915691753338712193L;

             public AskToExpireSessionEvent(final Object source) {
                     super(source);
             }

             @Override
             public String getSource() {
                     return (String)super.getSource();
             }


             public static AskToExpireSessionEvent of(final String sessionId) {
                     return new AskToExpireSessionEvent(sessionId);
             }
     }

http セッション キャッシング リスナー:

     import java.util.Map;
     import java.util.WeakHashMap;

     import javax.servlet.http.HttpSession;

     import org.slf4j.Logger;
     import org.slf4j.LoggerFactory;
     import org.springframework.beans.factory.annotation.Autowired;
     import org.springframework.context.ApplicationListener;
     import org.springframework.security.web.session.HttpSessionCreatedEvent;
     import org.springframework.security.web.session.HttpSessionDestroyedEvent;
     import org.springframework.stereotype.Component;

     import com.cb4.base.service.event.AskToExpireSessionEvent;


     @Component
     public class HttpSessionCachingListener {

             private static final Logger logger = LoggerFactory.getLogger(HttpSessionCachingListener.class);

             private final Map<String, HttpSession> sessionCache = new WeakHashMap<>();

             void onHttpSessionCreatedEvent(final HttpSessionCreatedEvent event){
                     if (event != null && event.getSession() != null && event.getSession().getId() != null) {
                             sessionCache.put(event.getSession().getId(), event.getSession());
                     }
             }

             void onHttpSessionDestroyedEvent(final HttpSessionDestroyedEvent event){
                     if (event != null && event.getSession() != null && event.getSession().getId() != null){
                             sessionCache.remove(event.getSession().getId());
                     }
             }

             public void timeOutSession(final String sessionId){
                     if(sessionId != null){
                             final HttpSession httpSession = sessionCache.get(sessionId);
                             if(null != httpSession){
                                     logger.debug("invalidating session {} in 1 second", sessionId);
                                     httpSession.setMaxInactiveInterval(1);
                             }
                     }
             }

             @Component
             static class HttpSessionCreatedLisener implements ApplicationListener<HttpSessionCreatedEvent> {

                     @Autowired
                     HttpSessionCachingListener parent;

                     @Override
                     public void onApplicationEvent(final HttpSessionCreatedEvent event) {
                             parent.onHttpSessionCreatedEvent(event);
                     }
             }

             @Component
             static class HttpSessionDestroyedLisener implements ApplicationListener<HttpSessionDestroyedEvent> {

                     @Autowired
                     HttpSessionCachingListener parent;

                     @Override
                     public void onApplicationEvent(final HttpSessionDestroyedEvent event) {
                             parent.onHttpSessionDestroyedEvent(event);
                     }
             }

             @Component
             static class AskToTimeOutSessionLisener implements ApplicationListener<AskToExpireSessionEvent> {

                     @Autowired
                     HttpSessionCachingListener parent;

                     @Override
                     public void onApplicationEvent(final AskToExpireSessionEvent event) {
                             if(event != null){
                                     parent.timeOutSession(event.getSource());
                             }
                     }
             }

     }
于 2016-02-08T18:21:38.297 に答える