春季安全性,如何使用户的所有会话期满 [英] spring security, how to expire all sessions of a user

查看:82
本文介绍了春季安全性,如何使用户的所有会话期满的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须解决以下情况,在Spring Security 3.2.5-RELEASE中,其中Spring Core 4.1.2-RELEASE应用程序在wildfly 8.1上运行Java 1.7.

I have to solve the following scenario, in a Spring Security 3.2.5-RELEASE with Spring Core 4.1.2-RELEASE application running Java 1.7 on wildfly 8.1.

  1. 用户"bob"登录
  2. 然后管理员删除"bob"
  3. 如果"bob"注销,则他无法再次登录.但是他的当前会话仍处于活动状态.
  4. 我想踢出鲍勃"

  1. user 'bob' logs in
  2. and Admin deletes 'bob'
  3. if 'bob' logs out, he can't log in. again but he`s current session remains active.
  4. i want to kick 'bob' out

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

推荐答案

  1. 添加应用程序事件侦听器以跟踪HttpSessionCreatedEventHttpSessionDestroyedEvent并将其注册为ApplicationListener并维护SessionId到HttoSession的缓存.
  2. (可选)添加您自己的ApplicationEvent类AskToExpireSessionEvent-
  3. 用户管理服务中的
  4. 将依赖项添加到SessionRegistryApplicationEventPublisher,以便您可以列出当前活动的用户会话,并找到正在寻找的用户活动的会话(因为可能有很多)即"bob"
  5. 在删除用户时,将为每个会话分配一个AskToExpireSessionEvent.
  6. 使用弱引用HashMap跟踪会话
  1. add application event listener to track HttpSessionCreatedEvent and HttpSessionDestroyedEvent and register it as an ApplicationListener and maintain a cache of SessionId to HttoSession.
  2. (optional) add your own ApplicationEvent class AskToExpireSessionEvent -
  3. in you user management service add dependencies to SessionRegistry and ApplicationEventPublisher so that you could list through the currently active user sessions and find the ones (cause there could be many) which are active for the user you are looking for i.e. 'bob'
  4. when deleting a user dispatch an AskToExpireSessionEvent for each of his sessions.
  5. use a weak reference HashMap to track the sessions

用户服务:

     @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());
                             }
                     }
             }

     }

这篇关于春季安全性,如何使用户的所有会话期满的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆