| package com.doumee.config.shiro; | 
|   | 
| import com.alibaba.fastjson.JSON; | 
| import com.doumee.core.model.ApiResponse; | 
| import com.doumee.core.model.LoginUserInfo; | 
| import com.doumee.core.utils.Constants; | 
| import org.apache.commons.lang3.StringUtils; | 
| import org.apache.shiro.cache.Cache; | 
| import org.apache.shiro.cache.MapCache; | 
| import org.apache.shiro.session.Session; | 
| import org.apache.shiro.session.mgt.DefaultSessionKey; | 
| import org.apache.shiro.session.mgt.SessionManager; | 
| import org.apache.shiro.subject.Subject; | 
| import org.apache.shiro.web.filter.authc.FormAuthenticationFilter; | 
| import org.springframework.http.HttpStatus; | 
|   | 
| import javax.servlet.ServletRequest; | 
| import javax.servlet.ServletResponse; | 
| import javax.servlet.http.HttpServletResponse; | 
| import java.io.Serializable; | 
| import java.util.Deque; | 
| import java.util.LinkedList; | 
|   | 
| /** | 
|  * Shiro认证过滤器,处理未认证情况的响应 | 
|  * @author Eva.Caesar Liu | 
|  * @date 2023/04/17 12:11 | 
|  */ | 
| public class ShiroAuthFilter extends FormAuthenticationFilter { | 
|   | 
|     public ShiroAuthFilter(SessionManager sessionManager,ShiroCacheManager shiroCacheManager) { | 
|         super(); | 
|         this.sessionManager =   (ShiroSessionManager)sessionManager; | 
|         this.cache = shiroCacheManager.getCache("shiro_redis_cache"); | 
|     } | 
|     @Override | 
|     protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)  { | 
|         return false; | 
|     } | 
|   | 
|     private int maxSession = 1; //最大会话数量 | 
|   | 
|     private boolean kickOutAfter = false;   //踢出前者还是后者 | 
|     private Cache<String, Deque<Serializable>> cache; //缓存管理 | 
|   | 
|   | 
|     private ShiroSessionManager sessionManager;  //会话管理 | 
|   | 
|     @Override | 
|     protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { | 
|         Subject subject = getSubject(request, response); | 
|         if (!subject.isAuthenticated() && !subject.isRemembered()) { //如果不是认证过和记住密码的,就直接放行请求,避免造成访问过慢 | 
|            // return Boolean.TRUE; | 
|         } | 
|         Session session = subject.getSession(); //获取会话session | 
|         Object principal = subject.getPrincipal(); | 
|         Serializable sessionId = session.getId(); | 
|         LoginUserInfo userInfo = (LoginUserInfo) principal; | 
|         if(userInfo == null || !Constants.equalsInteger(userInfo.getType(), Constants.UserType.ZHUBO.getKey()) ){ | 
|             HttpServletResponse servletResponse = (HttpServletResponse) response; | 
|             servletResponse.setHeader("content-type", "application/json;charset=UTF-8"); | 
|             servletResponse.getWriter().write(JSON.toJSONString(ApiResponse.failed(HttpStatus.UNAUTHORIZED.value(), "未登录或登录信息已过期"))); | 
|             return Boolean.FALSE; | 
|         } | 
|         String userName = userInfo.getCompanyId() +"_"+ userInfo.getId(); | 
|         Deque<Serializable> deque = cache.get(userName); | 
|         if (deque == null) { | 
|             deque = new LinkedList<>(); | 
|         } | 
|         if (!deque.contains(sessionId) && session.getAttribute("kickOut") == null) { | 
|             deque.push(sessionId); | 
|             cache.put(userName, deque); | 
|         } | 
|         while (deque.size() > maxSession) { | 
|             Serializable kickOutSessionId; | 
|             if (kickOutAfter) { | 
|                 kickOutSessionId = deque.removeFirst(); | 
|                 cache.put(userName, deque); | 
|             } else { | 
|                 kickOutSessionId = deque.removeLast(); | 
|                 cache.put(userName, deque); | 
|             } | 
|   | 
|             try { | 
|                 Session kickOutSession = sessionManager.getSession(new DefaultSessionKey(kickOutSessionId)); | 
|                 if (kickOutSession != null){ | 
|                     kickOutSession.setAttribute("kickOut", Boolean.TRUE); | 
|                 } | 
|             } catch (Exception e) { | 
|                 e.printStackTrace(); | 
|             } | 
|         } | 
|   | 
|         if (session!=null && session.getAttribute("kickOut") != null && (Boolean) session.getAttribute("kickOut") == true) { | 
|             try { | 
|                 subject.logout(); | 
|                 if(deque!=null){ | 
|                     deque.remove(sessionId); | 
|                     cache.put(userName, deque); | 
|                 } | 
|             } catch (Exception e) { | 
|                 e.printStackTrace(); | 
|             } | 
|             saveRequest(request); | 
|             HttpServletResponse servletResponse = (HttpServletResponse) response; | 
|             servletResponse.setHeader("content-type", "application/json;charset=UTF-8"); | 
|             servletResponse.getWriter().write(JSON.toJSONString(ApiResponse.failed(HttpStatus.UNAUTHORIZED.value(), "未登录或登录信息已过期"))); | 
|             return Boolean.FALSE; | 
|         } | 
|         return Boolean.TRUE; | 
|     } | 
|   | 
|     public int getMaxSession() { | 
|         return maxSession; | 
|     } | 
|   | 
|     public void setMaxSession(int maxSession) { | 
|         this.maxSession = maxSession; | 
|     } | 
|   | 
|     public boolean isKickOutAfter() { | 
|         return kickOutAfter; | 
|     } | 
|   | 
|     public void setKickOutAfter(boolean kickOutAfter) { | 
|         this.kickOutAfter = kickOutAfter; | 
|     } | 
|   | 
|     public Cache<String, Deque<Serializable>> getCache() { | 
|         return cache; | 
|     } | 
|   | 
|     public void setCache(Cache<String, Deque<Serializable>> cache) { | 
|         this.cache = cache; | 
|     } | 
|   | 
|     public ShiroSessionManager getSessionManager() { | 
|         return sessionManager; | 
|     } | 
|   | 
|     public void setSessionManager(ShiroSessionManager sessionManager) { | 
|         this.sessionManager = sessionManager; | 
|     } | 
| } |