我在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也没有返回我在第三方会话创建调用期间设置的会话。
任何帮助将不胜感激。 谢谢!
答案 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;
}
}
谢谢!