package com.javaweb.framework.shiro.web.session; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import org.apache.commons.lang3.time.DateUtils; import org.apache.shiro.session.ExpiredSessionException; import org.apache.shiro.session.InvalidSessionException; import org.apache.shiro.session.Session; import org.apache.shiro.session.mgt.DefaultSessionKey; import org.apache.shiro.session.mgt.SessionKey; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.javaweb.common.constant.ShiroConstants; import com.javaweb.common.utils.StringUtils; import com.javaweb.common.utils.bean.BeanUtils; import com.javaweb.common.utils.spring.SpringUtils; import com.javaweb.framework.shiro.session.OnlineSession; import com.javaweb.system.domain.SysUserOnline; import com.javaweb.system.service.ISysUserOnlineService; /** * 主要是在此如果会话的属性修改了 就标识下其修改了 然后方便 OnlineSessionDao同步 * * @author ruoyi */ public class OnlineWebSessionManager extends DefaultWebSessionManager { private static final Logger log = LoggerFactory.getLogger(OnlineWebSessionManager.class); @Override public void setAttribute(SessionKey sessionKey, Object attributeKey, Object value) throws InvalidSessionException { super.setAttribute(sessionKey, attributeKey, value); if (value != null && needMarkAttributeChanged(attributeKey)) { OnlineSession session = getOnlineSession(sessionKey); session.markAttributeChanged(); } } private boolean needMarkAttributeChanged(Object attributeKey) { if (attributeKey == null) { return false; } String attributeKeyStr = attributeKey.toString(); // 优化 flash属性没必要持久化 if (attributeKeyStr.startsWith("org.springframework")) { return false; } if (attributeKeyStr.startsWith("javax.servlet")) { return false; } if (attributeKeyStr.equals(ShiroConstants.CURRENT_USERNAME)) { return false; } return true; } @Override public Object removeAttribute(SessionKey sessionKey, Object attributeKey) throws InvalidSessionException { Object removed = super.removeAttribute(sessionKey, attributeKey); if (removed != null) { OnlineSession s = getOnlineSession(sessionKey); s.markAttributeChanged(); } return removed; } public OnlineSession getOnlineSession(SessionKey sessionKey) { OnlineSession session = null; Object obj = doGetSession(sessionKey); if (StringUtils.isNotNull(obj)) { session = new OnlineSession(); BeanUtils.copyBeanProp(session, obj); } return session; } /** * 验证session是否有效 用于删除过期session */ @Override public void validateSessions() { if (log.isInfoEnabled()) { log.info("invalidation sessions..."); } int invalidCount = 0; int timeout = (int) this.getGlobalSessionTimeout(); Date expiredDate = DateUtils.addMilliseconds(new Date(), 0 - timeout); ISysUserOnlineService userOnlineService = SpringUtils.getBean(ISysUserOnlineService.class); List userOnlineList = userOnlineService.selectOnlineByExpired(expiredDate); // 批量过期删除 List needOfflineIdList = new ArrayList(); for (SysUserOnline userOnline : userOnlineList) { try { SessionKey key = new DefaultSessionKey(userOnline.getSessionId()); Session session = retrieveSession(key); if (session != null) { throw new InvalidSessionException(); } } catch (InvalidSessionException e) { if (log.isDebugEnabled()) { boolean expired = (e instanceof ExpiredSessionException); String msg = "Invalidated session with id [" + userOnline.getSessionId() + "]" + (expired ? " (expired)" : " (stopped)"); log.debug(msg); } invalidCount++; needOfflineIdList.add(userOnline.getSessionId()); } } if (needOfflineIdList.size() > 0) { try { userOnlineService.batchDeleteOnline(needOfflineIdList); } catch (Exception e) { log.error("batch delete db session error.", e); } } if (log.isInfoEnabled()) { String msg = "Finished invalidation session."; if (invalidCount > 0) { msg += " [" + invalidCount + "] sessions were stopped."; } else { msg += " No sessions were stopped."; } log.info(msg); } } @Override protected Collection getActiveSessions() { throw new UnsupportedOperationException("getActiveSessions method not supported"); } }