package com.norteksoft.acs.web.filter; import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Timer; import java.util.TimerTask; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.security.context.SecurityContextImpl; import com.norteksoft.acs.entity.sale.SubscriberItem; import com.norteksoft.acs.entity.security.User; import com.norteksoft.acs.service.sale.SubscriberItemManager; import com.norteksoft.acs.web.listener.AcsHttpSessionListener; import com.norteksoft.product.util.ContextUtils; import com.norteksoft.product.util.SystemUrls; /** * */ @SuppressWarnings("deprecation") public class ExceededOnlineUserFilter implements Filter { private static Log log = LogFactory.getLog(ExceededOnlineUserFilter.class); public void destroy() { } public void doFilter(ServletRequest req, ServletResponse rep, FilterChain chan) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) rep; Long companyId = ContextUtils.getCompanyId(); if(companyId == null){ // 用户没有登录时,由权限模块控制权限 chan.doFilter(req, rep); return; } String url=request.getRequestURI(); String sysCode = SystemUrls.getSysCodeFromUri(url); if(url.contains("/j_spring_security_logout")){ removeConcurrencyStorage(request.getSession()); } if(url.contains("exception-handle.action")||url.contains("update-password.action")){ chan.doFilter(req, rep); return; } String username = ContextUtils.getLoginName(); if(username == null || "roleAnonymous".equals(username)){ chan.doFilter(req, rep); }else{ boolean isFirstAccess = ConcurrencyStorage.isFirstAccess(companyId, sysCode); log.debug(username+" Access [companyId:"+companyId+", systemCode:"+sysCode+", isFirstAccess:"+isFirstAccess+"]"); boolean allowed = false; if(isFirstAccess){ // 应用第一次访问时,判断订单 // 根据系统编号查询系统的订单项 SubscriberItemManager manager = (SubscriberItemManager)ContextUtils.getBean("subscriberItemManager"); List<SubscriberItem> items = manager.queryItems(companyId, sysCode); // 判断订单是否在有效期内 Calendar cal = Calendar.getInstance(); cal.add(Calendar.DAY_OF_YEAR, -1); Date current = cal.getTime(); for(SubscriberItem item : items){ log.debug(" Item [id:"+item.getId()+", EffectDate:"+item.getEffectDate() +", InvalidDate:"+item.getInvalidDate()+", Concurrency:"+item.getConcurrency()+"]"); if(current.after(item.getEffectDate()) && current.before(item.getInvalidDate())){ ConcurrencyStorage.putConcurrency(companyId+sysCode, item.getConcurrency()); if(item.getConcurrency() > 0){ ConcurrencyStorage.put(companyId+sysCode, username); allowed = true; } } } }else{ // 判断并发数 boolean containUser = ConcurrencyStorage.containsUser(companyId, sysCode, username); log.debug(" concurrency storage contains "+username+" "+containUser); if(containUser){ allowed=true; } else{ if(ConcurrencyStorage.allowe(companyId+sysCode)){ allowed=true; ConcurrencyStorage.put(companyId+sysCode, username); } } } log.debug(" concurrency result "+allowed); if(allowed){ chan.doFilter(req, rep); }else{ // 产品已过期 或 超出并发人数限制 String imatrixUrl=SystemUrls.getSystemUrl("imatrix"); String imatrixCode=imatrixUrl.substring(imatrixUrl.lastIndexOf("/")+1); if(imatrixCode.contains(".")){//判断是否是80端口,是80端口时 imatrixCode=""; } response.sendRedirect(imatrixCode+"/portal/exception-handle.action?type=403&exceed=true"); } } } public void init(FilterConfig config) throws ServletException { String code = config.getServletContext().getInitParameter("systemCode"); if("imatrix".equals(code)){ ConcurrencyStorage.getSysCodes().add("portal"); ConcurrencyStorage.getSysCodes().add("acs"); ConcurrencyStorage.getSysCodes().add("mms"); ConcurrencyStorage.getSysCodes().add("bs"); ConcurrencyStorage.getSysCodes().add("wf"); ConcurrencyStorage.getSysCodes().add("task"); } sessionInvalidateTimer(); } private void sessionInvalidateTimer(){ Timer timer = new Timer("session timer", true); // 定时验证session TimerTask task = new TimerTask(){ public void run() { try { validateSessionTime(); } catch (Exception e) { log.error(" validate session timeout error: ", e); } }}; timer.schedule(task, 1*60000, 1*60000); // 定时移除并发信息 TimerTask clearStorageTask = new TimerTask(){ public void run() { try { log.debug(" clean storage ... "); ConcurrencyStorage.cleanStorage(); } catch (Exception e) { log.error(" clean storage error: ", e); } }}; Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, 0); cal.add(Calendar.DAY_OF_YEAR, 1); cal.setTimeInMillis(cal.getTimeInMillis()); timer.schedule(clearStorageTask, cal.getTime(), 24*60*60000l); } private void validateSessionTime(){ //ConcurrencyStorage.printStorage(); SingleSignOutFilter.SessionStorage mapping = (SingleSignOutFilter.SessionStorage) SingleSignOutFilter.getSessionMappingStorage(); //System.out.println("======================== "+mapping.values().size()+" ========================"); Iterator<HttpSession> it = mapping.values().iterator(); HttpSession session = null; while(it.hasNext()){ session = it.next(); boolean invalidation = true; try{ invalidation = SessionFailFilter.isSessionFail(session); if(invalidation){ removeConcurrencyStorage(session); // 记录用户退出日志 AcsHttpSessionListener.recordLogout(session); //System.out.println("============ log out ==============="); } }catch(Exception e){ log.error(e); } } } public static void removeConcurrencyStorage(HttpSession session){ if(session == null) return; SecurityContextImpl context = (SecurityContextImpl)session.getAttribute("SPRING_SECURITY_CONTEXT"); if(context != null){ User user = (User)context.getAuthentication().getPrincipal(); ConcurrencyStorage.remove(user.getCompanyId(), user.getUsername()); } } public static class ConcurrencyStorage{ private ConcurrencyStorage(){} // 存储公司各系统的并发人数 private static Map<String, Integer> concurrencyStorage = new HashMap<String, Integer>(); // 存储公司各系统的在线用户 private static Map<String, Set<String>> storage = new HashMap<String, Set<String>>(); private static List<String> sysCodes = new ArrayList<String>(); static void cleanStorage(){ concurrencyStorage = new HashMap<String, Integer>(); storage = new HashMap<String, Set<String>>(); } public static void putConcurrency(String key, Integer value){ concurrencyStorage.put(key, value); } public static Integer getConcurrency(String key){ return concurrencyStorage.get(key); } public static synchronized boolean isFirstAccess(Long companyId, String sysCode){ return concurrencyStorage.get(companyId+sysCode) == null; } public static boolean containsUser(Long companyId, String sysCode, String loginName){ return storage.get(companyId+sysCode) != null && storage.get(companyId+sysCode).contains(loginName); } public static synchronized void remove(Long companyId, String username){ for(String code : sysCodes){ if(storage.get(companyId+code) != null){ log.debug(" remove user : [company: "+companyId+", code: "+code+", name: "+username+"]"); storage.get(companyId+code).remove(username); } } } public static synchronized void put(String key, String value){ if(storage.containsKey(key)){ storage.get(key).add(value); }else{ Set<String> set = new LinkedHashSet<String>(); set.add(value); storage.put(key, set); } } public static synchronized boolean allowe(String key){ return storage.get(key)!=null && (storage.get(key).size() < concurrencyStorage.get(key)); } static void printStorage(){ if(storage != null) for(Map.Entry<String,Set<String>> kv : storage.entrySet()){ System.out.println("===================== "+kv.getKey()+" ====================="); for(String name : kv.getValue()){ System.out.println("== "+name+" =="); } } } public static List<String> getSysCodes() { return sysCodes; } } }