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> 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 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> getCache() { return cache; } public void setCache(Cache> cache) { this.cache = cache; } public ShiroSessionManager getSessionManager() { return sessionManager; } public void setSessionManager(ShiroSessionManager sessionManager) { this.sessionManager = sessionManager; } }