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;
|
}
|
}
|