最近被外地的同事问到一个问题:平台网站退出登录以后,无法清除子系统的session,大致过程是这样的,点击平台上的功能按钮进入子系统,模拟登录,成功后可以使用子系统的所有功能。平台点击退出的时候平台服务器发送一个post请求,请求子系统清除session。
听了问题以后首先考虑的是跨域导致找不到登录时候保存的session。
解决思路:将问题拆分,
第一:找到登录时候的session。
第二:退出登录时候对步骤一中的session做标记。
第三:在过滤器中遇到这个session的时候将session置位无效。
详细实现过程:说下项目背景,项目采用SSH,缓存用memcache。平台请求都会携带一个唯一标识(ssoSign)。
第一:在登录的时候以ssoSign为key值,request中的session的id为value保存到memcache中。
第二:在退出登录的时候根据ssoSign从memecache中查询到相应的sessionId,并将这个sessionId保存的 memcache中。
第三:修改过滤器,当有request到达时检测sessionId是否存在于memcache中,如果存在将该reqeust对应的 session设为过期即可。
需要注意的问题是web项目的启动顺序 过滤器是在bean初始化之前的,在过滤器中的自动注入是无效的,可以自己写一个方法获取到相应的bean,下面代码是一个工具类,通过SpringUtils.getBean("beanName") 获取到相应的bean。
@Component
public class SpringUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
if (SpringUtils.applicationContext == null) {
SpringUtils.applicationContext = applicationContext;
}
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//根据name
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
//根据类型
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}