package com.doumee.config.shiro; import java.io.Serializable; import java.util.Collection; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.SerializationUtils; import org.apache.shiro.session.Session; import org.apache.shiro.session.UnknownSessionException; import org.apache.shiro.session.mgt.SimpleSession; import org.apache.shiro.session.mgt.eis.SessionDAO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; //@Component @Slf4j @SuppressWarnings({ "rawtypes", "unchecked" }) public class ShiroRedisSessionDAO implements SessionDAO { // Session超时时间,单位为毫秒 private static final String KEY_PREFIX = "shiro:session:"; private long expireTime = 120000; @Autowired private ShiroTokenManager shiroTokenManager; @Autowired private RedisTemplate redisTemplate;// Redis操作类,对这个使用不熟悉的,可以参考前面的博客 // @Autowired // private StringRedisTemplate redisTemplate; public ShiroRedisSessionDAO() { super(); } public ShiroRedisSessionDAO(long expireTime, StringRedisTemplate redisTemplate) { super(); this.expireTime = expireTime; this.redisTemplate = redisTemplate; } @Override // 更新session public void update(Session session) throws UnknownSessionException { System.out.println("===============update================"); if (session == null || session.getId() == null) { return; } session.setTimeout(expireTime); byte[] bytes = SerializationUtils.serialize((Serializable) session); redisTemplate.opsForValue().set(KEY_PREFIX+session.getId(), bytes, expireTime, TimeUnit.MILLISECONDS); } @Override // 删除session public void delete(Session session) { System.out.println("===============delete================"); if (null == session) { return; } redisTemplate.opsForValue().getOperations().delete(KEY_PREFIX+session.getId()); } @Override// 获取活跃的session,可以用来统计在线人数,如果要实现这个功能,可以在将session加入redis时指定一个session前缀,统计的时候则使用keys("session-prefix*")的方式来模糊查找redis中所有的session集合 public Collection getActiveSessions() { System.out.println("==============getActiveSessions================="); return redisTemplate.keys("*"); } @Override public Serializable create(Session session) { System.out.println("===============doCreate================"); if (session == null) { log.error("session is null"); throw new UnknownSessionException("session is null"); } Serializable sessionId = shiroTokenManager.build(); ((SimpleSession)session).setId(sessionId); byte[] bytes = SerializationUtils.serialize((Serializable) session); redisTemplate.opsForValue().set(session.getId(), bytes, expireTime, TimeUnit.MILLISECONDS); return sessionId; } public Session readSession(Serializable sessionId) throws UnknownSessionException{ if (sessionId == null) { log.warn("session id is null"); return null; } if (sessionId instanceof String) { // 对SessionId进行验证(可用于防止Session捕获、暴力捕捉等一系列安全问题,最终安全性取决于check如何实现) shiroTokenManager.check((String) sessionId); } log.debug("read session from cache"); SimpleSession simpleSession = (SimpleSession) SerializationUtils.deserialize((byte[])redisTemplate.opsForValue().get(KEY_PREFIX+sessionId)); return simpleSession; } public long getExpireTime() { return expireTime; } public void setExpireTime(long expireTime) { this.expireTime = expireTime; } public RedisTemplate getRedisTemplate() { return redisTemplate; } public void setRedisTemplate(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } }