架构|(原创)springboot+shiro+redis 限制同用户多次登录(不需要考虑sprinboot、redis版本)

架构|(原创)springboot+shiro+redis 限制同用户多次登录(不需要考虑sprinboot、redis版本)
文章图片

如果你还在为上面的错误而烦恼。还要听从网上说找合适的版本去解决。来到这篇文章,你的电脑算是保住了。
让我们来分析下问题所在。其实就是实体类RedisSessionDAO中方法getActiveSessions具体是
redisManager.keys行的问题。有兴趣的可以继续找redisManager.keys下面的代码。
架构|(原创)springboot+shiro+redis 限制同用户多次登录(不需要考虑sprinboot、redis版本)
文章图片


如果考虑换版本之类的,有可能对整体框架都是有影响的。所以我们要换种思路。既然是shiro内在的redis出的问题。那我能不能摒弃他们的redis。答案是:当然可以了!
做法就是自定义个RedisSessionDAO,重写他们的方法。
【架构|(原创)springboot+shiro+redis 限制同用户多次登录(不需要考虑sprinboot、redis版本)】架构|(原创)springboot+shiro+redis 限制同用户多次登录(不需要考虑sprinboot、redis版本)
文章图片


然后你在按照下面这样获取活跃的用户,去处理自己的逻辑
架构|(原创)springboot+shiro+redis 限制同用户多次登录(不需要考虑sprinboot、redis版本)
文章图片

项目经理都夸你是个人才。
好了。代码给你放下面了。有问题具体私我。

package com.changfa.config.shiro; import com.changfa.config.RedisConfig; import com.changfa.constants.UserConstants; import org.apache.shiro.session.Session; import org.apache.shiro.session.UnknownSessionException; import org.crazycake.shiro.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.Serializable; import java.util.*; import java.util.concurrent.TimeUnit; /** * @author wwz */ public class CustomRedisSessionDAOextends RedisSessionDAO{private static Logger logger = LoggerFactory.getLogger(RedisSessionDAO.class); private static final String DEFAULT_SESSION_KEY_PREFIX = "shiro:session:"; private String keyPrefix = "shiro:session:"; private static final long DEFAULT_SESSION_IN_MEMORY_TIMEOUT = 1000L; private long sessionInMemoryTimeout = 1000L; private static final int DEFAULT_EXPIRE = 1800; private int expire = 1800; private static final int MILLISECONDS_IN_A_SECOND = 1000; private IRedisManager redisManager; private RedisSerializer keySerializer = new StringSerializer(); private RedisSerializer valueSerializer = new ObjectSerializer(); private static ThreadLocal sessionsInThread = new ThreadLocal(); private RedisConfig.ByteRedisTemplate redisTemplate; public CustomRedisSessionDAO() { }@Override public void update(Session session) throws UnknownSessionException { this.saveSession(session); }private void saveSession(Session session) throws UnknownSessionException { if (session != null && session.getId() != null) { if ((long)(this.expire * 1000) < session.getTimeout()) { logger.warn("Redis session expire time: " + this.expire * 1000 + " is less than Session timeout: " + session.getTimeout() + " . It may cause some problems."); } byte[] value = https://www.it610.com/article/new byte[0]; try { value = valueSerializer.serialize(session); redisTemplate.opsForValue().set(this.getRedisSessionKey(session.getId()),value,this.expire, TimeUnit.SECONDS); } catch (SerializationException e) { e.printStackTrace(); } // this.redisManager.set(key, value, this.expire); } else { logger.error("session or session id is null"); throw new UnknownSessionException("session or session id is null"); } }@Override public void delete(Session session) { if (session != null && session.getId() != null) { try { redisTemplate.delete(this.getRedisSessionKey(session.getId())); //this.redisManager.del(this.keySerializer.serialize(this.getRedisSessionKey(session.getId()))); } catch (Exception var3) { logger.error("delete session error. session id=" + session.getId()); }} else { logger.error("session or session id is null"); } } @Override public Collection getActiveSessions() { HashSet sessions = new HashSet(); try { Set keys = redisTemplate.keys(this.keyPrefix + "*"); if (keys != null && keys.size() > 0) { Iterator i$ = keys.iterator(); while(i$.hasNext()) { String key = (String)i$.next(); Session s = (Session)valueSerializer.deserialize((byte[]) this.redisTemplate.opsForValue().get(key)); Object o = s.getAttribute(UserConstants.USER_KEY); if(o != null){ sessions.add(s); } } } } catch (Exception var6) { logger.error("get active sessions error."); }return sessions; }@Override protected Serializable doCreate(Session session) { if (session == null) { logger.error("session is null"); throw new UnknownSessionException("session is null"); } else { Serializable sessionId = this.generateSessionId(session); this.assignSessionId(session, sessionId); this.saveSession(session); return sessionId; } }@Override protected Session doReadSession(Serializable sessionId) { if (sessionId == null) { logger.warn("session id is null"); return null; } else { Session s = this.getSessionFromThreadLocal(sessionId); if (s != null) { return s; } else { logger.debug("read session from redis"); try { s = (Session)this.valueSerializer.deserialize((byte[]) this.redisTemplate.opsForValue().get(this.getRedisSessionKey(sessionId))); // s = (Session)this.valueSerializer.deserialize(this.redisManager.get(this.keySerializer.serialize(this.getRedisSessionKey(sessionId)))); this.setSessionToThreadLocal(sessionId, s); } catch (Exception var4) { logger.error("read session error. settionId=" + sessionId); }return s; } } }private void setSessionToThreadLocal(Serializable sessionId, Session s) { Map sessionMap = (Map)sessionsInThread.get(); if (sessionMap == null) { sessionMap = new HashMap(); sessionsInThread.set(sessionMap); }SessionInMemory sessionInMemory = new SessionInMemory(); sessionInMemory.setCreateTime(new Date()); sessionInMemory.setSession(s); ((Map)sessionMap).put(sessionId, sessionInMemory); }private Session getSessionFromThreadLocal(Serializable sessionId) { Session s = null; if (sessionsInThread.get() == null) { return null; } else { Map sessionMap = (Map)sessionsInThread.get(); SessionInMemory sessionInMemory = (SessionInMemory)sessionMap.get(sessionId); if (sessionInMemory == null) { return null; } else { Date now = new Date(); long duration = now.getTime() - sessionInMemory.getCreateTime().getTime(); if (duration < this.sessionInMemoryTimeout) { s = sessionInMemory.getSession(); logger.debug("read session from memory"); } else { sessionMap.remove(sessionId); }return s; } } }private String getRedisSessionKey(Serializable sessionId) { return this.keyPrefix + sessionId; }public RedisConfig.ByteRedisTemplate getRedisTemplate() { return redisTemplate; }public void setRedisTemplate(RedisConfig.ByteRedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } }

    推荐阅读