在Spring Security Session期间捕获第三方Web服务会话ID

时间:2014-01-28 18:27:41

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

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

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

我创建了一个Logout Listener,它可以像这样监听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();
    }
}

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

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

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

我修复了调用Logout / Session超时的单独线程的问题。 我创建了一个新的自定义User类并扩展了原始spring“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;
    }

}

谢谢!