简单实现全系统session管理

web.xml中增加SessionListener

<listener>
   <listener-class>com.workbgm.common.listener.SessionListener</listener-class>
</listener>

SessionListener类

package com.workbgm.common.listener;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class SessionListener implements HttpSessionListener {
    private MySessionContext context = MySessionContext.getSessionContext();

    @Override
    public void sessionCreated(HttpSessionEvent e) {
//        context.addSession(e.getSession());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent e) {
        context.delSession(e.getSession());//只是处理session超时的情况
    }

}

说明:前面这一堆只是为了在session超时时,更新最新的session状态!

MySessionContenxt类

package com.workbgm.common.listener;
import com.workbgm.grid.interceptor.LoginInterceptor;
import com.workbgm.grid.model.vo.data.LoginUserInfo;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpSession;

public class MySessionContext {
    private static MySessionContext context;

    private Map<String, HttpSession> map;

    private MySessionContext() {
        map = new HashMap<>();
    }

    public static MySessionContext getSessionContext() {
        if(context == null) {
            context = new MySessionContext();
        }
        return context;
    }

   //添加
public synchronized void addSession(HttpSession session) {
    if(session!= null) {
        LoginUserInfo loginUserInfo = (LoginUserInfo) session.getAttribute(LoginInterceptor.SESSION_USER);
        if(loginUserInfo!=null) {
            //登录名-用户ID作为key,你可以定义你自己的
            String key=loginUserInfo.getSysUser().getUsername()+"-"+loginUserInfo.getSysUser().getId();
            HttpSession oldSession=this.getSession(key);
            if(oldSession!=null) {
                String newUUID=  session.getAttribute(LoginInterceptor.SESSION_CSRF_TOKEN).toString();
                String oldUUID = oldSession.getAttribute(LoginInterceptor.SESSION_CSRF_TOKEN).toString();
                if (!newUUID.equals(oldUUID)) {//不同浏览器才处理
                    this.clearSession(key);
                }
            }
            map.put(key, session);
        }
    }
}

    //清除
    public synchronized void clearSession(String key){
        HttpSession oldSession=this.getSession(key);
        if(oldSession!=null){
            oldSession.invalidate();//让session失效
            map.remove(key);
        }
    }

    //获取
    public synchronized HttpSession getSession(String key) {
        if(key == null)
            return null;
        return map.get(key);
    }

    //删除
    public synchronized void delSession(HttpSession session) {
        if(session!= null){
            LoginUserInfo loginUserInfo = (LoginUserInfo) session.getAttribute(LoginInterceptor.SESSION_USER);
            if(loginUserInfo!=null) {
                String key=loginUserInfo.getSysUser().getUsername()+"-"+loginUserInfo.getSysUser().getId();
                clearSession(key);
            }
        }
    }

}

在用户登录的时候调用addSession方法,会踢掉之前登录的用户。

那么主动踢掉用户也很简单了,只需要增加一个UI界面,把MySessionContenxt的map展示出来,踢掉就调用clearSession方法就可以了,so easy!


2019年1月22日更新

______________________

MySessionContext的addSession方法做了更新,处理了没有关闭浏览器退出,无法重新登录的bug!
这里的SESSION_CSRF_TOKEN,为了防止CSRF攻击顺便处理了同一浏览器session区分的问题,其赋值是在用户登录的时候,形式如下:
this.setSessionAttr(LoginInterceptor.SESSION_CSRF_TOKEN,java.util.UUID.randomUUID());


评论区

JFinal

2018-12-11 16:22

代码十分简洁,感谢分享

北流家园网

2018-12-13 20:24

收藏

hhchor

2021-10-28 19:42