【问题标题】:capture the third party web service session Id during Spring Security Session在 Spring Security Session 期间捕获第三方 Web 服务会话 Id
【发布时间】:2014-02-20 05:41:09
【问题描述】:

我在 Spring MVC Web 应用程序中实现了 Spring 安全性。 出于身份验证目的,我使用 LDAP 和授权,我调用第三方 Web 服务,该服务为我提供所有授权以及会话 ID。

一旦用户注销或会话超时,我需要使用相同的会话 ID 再次调用第三方 Web 服务以使会话失效。

我创建了一个像这样监听 SessionDestroyedEvent 的注销监听器

public class LogoutListener implements ApplicationListener<SessionDestroyedEvent>{
    private SecurityServiceHandler securityServiceHandler;

    @Override
    public void onApplicationEvent(SessionDestroyedEvent event) {
        SecurityContext securityContext = event.getSecurityContext();
        UserDetails ud=null;
        if(securityContext!=null){
             ud = (UserDetails) securityContext.getAuthentication().getPrincipal();


        if(securityServiceHandler==null){
            securityServiceHandler = new SecurityServiceHandler();
        }
        //String sessionId = securityServiceHandler.getSessionId();
        String sessionId = VirgoSessionManager.getSessionId();

        System.out.println(ud.getUsername());
        System.out.println(VirgoSessionManager.getSessionId());

        securityServiceHandler.invalidateSession(ud.getUsername(),sessionId);

        //reset the sessionId 
        securityServiceHandler.setSessionId(null);
        }

    }

我在 VirgoSessionManager 类中使用了 ThreadLocal,如下所示

public class VirgoSessionManager {

    private static ThreadLocal<String> sessionId = new ThreadLocal<String>();

    public static String getSessionId(){

        return sessionId.get();
    }


    public static void setSessionId(String sId) {
        sessionId.set(sId);
    }

    public static void remove() {
        sessionId.remove();
    }
}

我的问题是 VirgoSessionManager 在会话创建成功后没有返回我在第三方会话创建调用期间设置的会话,即使我已经实现了线程本地。

任何帮助将不胜感激。 谢谢!

【问题讨论】:

    标签: spring session spring-mvc spring-security thread-local


    【解决方案1】:

    您可以使用完全不同的线程来提供注销功能,这会导致 ThreadLocal 变量中没有任何值。例如 tomcat 使用线程池,所以你需要在这里小心。尝试使用 getSessionId() 中的 Thread.currentThread().getName() 和 Thread.currentThread().getId() 以及您设置此值的位置记录/调试

    【讨论】:

      【解决方案2】:

      我解决了调用注销/会话超时的单独线程的问题。 我创建了一个新的自定义用户类并扩展了原始弹簧“org.springframework.security.core.userdetails.User”类。我在自定义用户类中添加了新字段“sessionId”。

      因此,每当我在注销/超时期间从 Spring SecurityContext 获取记录的用户详细信息时,我将始终拥有该 sessionId 并用于调用 invalidateSession 方法。

      我的自定义用户类如下所示。

      package com.wvo.custom.security;
      import java.util.Collection;
      import java.util.List;
      
      import org.springframework.security.core.GrantedAuthority;
      import org.springframework.security.core.userdetails.User;
      
      
      public class CustomUser extends User {
      
          private String virgoSessionId ;
          /**
           * 
           */
      
          private static final long serialVersionUID = 1L;
      
          public CustomUser(String username, String password,boolean enabled, boolean accountNonExpired, boolean accountNonLocked, boolean credentialsNonExpired,
                  Collection<? extends GrantedAuthority> authorities) {
               super(username, password,enabled, accountNonExpired, accountNonLocked, credentialsNonExpired, authorities);
          }
      
      
          public String getVirgoSessionId() {
              return virgoSessionId;
          }
      
          public void setVirgoSessionId(String virgoSessionId) {
              this.virgoSessionId = virgoSessionId;
          }
      
      }
      

      谢谢!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-04-11
        • 1970-01-01
        • 2019-02-20
        • 2015-06-13
        • 1970-01-01
        • 1970-01-01
        • 2011-02-06
        相关资源
        最近更新 更多