背景:框架Jfinal,使用Session保存账号信息
思路:在登录的使用获取sessionId 与user_id 加入map,每次请求接口使用拦截器验证。
1. 定义全局Map
public class UserSessionHelper {
private static ConcurrentHashMap<Integer, String> sessionIDMap = new ConcurrentHashMap<>();
public static Map<Integer, String> getSessionIDMap(){
return sessionIDMap;
}
public static void setSessionIDMap(Map<Integer, String> sessionIDMap){
sessionIDMap.putAll(sessionIDMap);
}
}
2. 生成一个单账号拦截类
public class SingleUserInterceptor implements Interceptor{
@Override
public void intercept(Invocation inv) {
Controller controller = inv.getController();
HttpServletRequest request = inv.getController().getRequest();
UserInfo userInfo = (UserInfo) request.getSession().getAttribute(LoginUtil.SESSION_USER_TAG);
if (userInfo != null) {
String sessionId = UserSessionHelper.getSessionIDMap().get(userInfo.getId());
if (sessionId != null && sessionId.equals(request.getSession().getId())) {
inv.invoke();
} else {
// 判断如果是异步请求,设置响应头 sessionstatus为timeout,自动跳转,否则重定向
if (request.getHeader("x-requested-with") != null
&& request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
System.out.println("同账号多人登录 user.id >>>>>>>>>>>>>>"+userInfo.getId());
request.getSession().invalidate();
request.getSession().setAttribute(LoginUtil.SESSION_USER_TAG, null);
request.getSession().setAttribute("loginflag", null);
request.getSession().setAttribute("casLogoutUrl", null);
controller.redirect("/login/logout");
} else {
try {
request.getSession().invalidate();
request.getSession().setAttribute(LoginUtil.SESSION_USER_TAG, null);
request.getSession().setAttribute("loginflag", null);
request.getSession().setAttribute("casLogoutUrl", null);
controller.redirect("/login/logout");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
3. 在Login中 存入Map
//20220714 add 为了同一个账号只能登录一人
String sessionId = getSession().getId();
if(!UserSessionHelper.getSessionIDMap().containsKey(user.getId())){//不存在,第一个人login
UserSessionHelper.getSessionIDMap().put(user.getId(), sessionId);
}else if(UserSessionHelper.getSessionIDMap().containsKey(user.getId())&&
!StringUtils.equals(sessionId, UserSessionHelper.getSessionIDMap().get(user.getId()))){//该账号存在但是sessionID不一致
UserSessionHelper.getSessionIDMap().remove(user.getId());
UserSessionHelper.getSessionIDMap().put(user.getId(), sessionId);
}
4. 第二步的java类加入config
/**
* 配置全局拦截器
*/
public void configInterceptor(Interceptors me) {
me.addGlobalActionInterceptor(new SingleUserInterceptor());
}
这样, 如果 两个A账号先登录, A1账号再次登录就会将A的session清除,A在请求其他接口的时候,被拦截器拦住,跳转到登出接口