使用到的redis KEY:
- session缓存hash:shiro-cache-authorization
- session存储value:shiro-cache-session:{sessionId}
ShrioRedisCache
@SuppressWarnings({ "unchecked", "rawtypes" })
public class ShiroRedisCache<HK, HV> implements Cache<HK, HV> {
private static final LoggerUtil logger = LoggerUtil.getLogger(ShiroRedisCache.class);
private static final String HASH_CACHE = "shiro-cache-authorization";
private final RedisTemplate _shiroRedisTemplate;
public ShiroRedisCache(RedisTemplate shiroRedisTemplate) {
this._shiroRedisTemplate = shiroRedisTemplate;
}
private String genCacheKey(Object key) {
return String.valueOf(key);
}
/*
* (non-Javadoc)
*
* @see org.apache.shiro.cache.Cache#clear()
*/
@Override
public void clear() throws CacheException {
_shiroRedisTemplate.delete(HASH_CACHE);
}
/*
* (non-Javadoc)
*
* @see org.apache.shiro.cache.Cache#get(java.lang.Object)
*/
@Override
public HV get(HK key) throws CacheException {
String relKey = genCacheKey(key);
return (HV) _shiroRedisTemplate.opsForHash().get(HASH_CACHE, relKey);
}
/*
* (non-Javadoc)
*
* @see org.apache.shiro.cache.Cache#keys()
*/
@Override
public Set<HK> keys() {
return _shiroRedisTemplate.opsForHash().keys(HASH_CACHE);
}
/*
* (non-Javadoc)
*
* @see org.apache.shiro.cache.Cache#put(java.lang.Object, java.lang.Object)
*/
@Override
public HV put(HK key, HV value) throws CacheException {
HV previos = get(key);
try {
logger.info("shiro-redis-cache-put:[{},{}]", key, value);
_shiroRedisTemplate.opsForHash().put(HASH_CACHE, genCacheKey(key), value);
} catch (Exception e) {
logger.error("put cache throw exception", e);
}
return previos;
}
/*
* (non-Javadoc)
*
* @see org.apache.shiro.cache.Cache#remove(java.lang.Object)
*/
@Override
public HV remove(HK key) throws CacheException {
HV previos = get(key);
logger.info("shiro-redis-cache-remove:[{},{}]", key, previos);
try {
_shiroRedisTemplate.opsForHash().delete(HASH_CACHE, genCacheKey(key));
} catch (Exception e) {
logger.error("remove cache throw exception", e);
}
return previos;
}
/*
* (non-Javadoc)
*
* @see org.apache.shiro.cache.Cache#size()
*/
@Override
public int size() {
return _shiroRedisTemplate.opsForHash().size(HASH_CACHE).intValue();
}
/*
* (non-Javadoc)
*
* @see org.apache.shiro.cache.Cache#values()
*/
@Override
public Collection<HV> values() {
return _shiroRedisTemplate.opsForHash().values(HASH_CACHE);
}
}
ShiroRedisCacheManager
@SuppressWarnings({ "rawtypes" })
public class ShiroRedisCacheManager implements CacheManager {
private RedisTemplate _redisTemplate;
/**
* @param redisTemplate
* the {@link #_redisTemplate} to set
*/
public void setShiroRedisTemplate(RedisTemplate redisTemplate) {
this._redisTemplate = redisTemplate;
}
@Override
public <K, V> Cache<K, V> getCache(String name) throws CacheException {
return new ShiroRedisCache<K, V>(_redisTemplate);
}
}
ShiroRedisSessionDao
@SuppressWarnings({ "unchecked", "rawtypes" })
public class ShiroRedisSessionDao extends AbstractSessionDAO {
private RedisTemplate<Object, Object> _shiroRedisTemplate;
private final static String REDIS_KEY_SHIRO = "shiro-cache-session:";
/**
* @param shiroRedisTemplate
* the {@link #_shiroRedisTemplate} to set
*/
public void setShiroRedisTemplate(RedisTemplate shiroRedisTemplate) {
this._shiroRedisTemplate = shiroRedisTemplate;
}
private String getSessionKey(Serializable sessionId) {
String preKey = REDIS_KEY_SHIRO + sessionId;
return preKey;
}
/*
* (non-Javadoc)
*
* @see org.apache.shiro.session.mgt.eis.SessionDAO#update(org.apache.shiro.
* session.Session)
*/
@Override
public void update(Session session) throws UnknownSessionException {
if (null == session || null == session.getId()) {
return;
}
String key = getSessionKey(session.getId());
Long timeOut = session.getTimeout() / 1000;
_shiroRedisTemplate.opsForValue().set(key, session, timeOut.intValue(), TimeUnit.SECONDS);
}
/*
* (non-Javadoc)
*
* @see org.apache.shiro.session.mgt.eis.SessionDAO#delete(org.apache.shiro.
* session.Session)
*/
@Override
public void delete(Session session) {
if (null == session) {
return;
}
Serializable id = session.getId();
if (id != null) {
_shiroRedisTemplate.delete(getSessionKey(id));
}
}
/*
* (non-Javadoc)
*
* @see org.apache.shiro.session.mgt.eis.SessionDAO#getActiveSessions()
*/
@Override
public Collection<Session> getActiveSessions() {
List<Session> sessions = Lists.newLinkedList();
Set<Object> keys = _shiroRedisTemplate.keys(getSessionKey("*"));
List<Object> sessDatas = _shiroRedisTemplate.opsForValue().multiGet(keys);
for (Object _session : sessDatas) {
if (_session instanceof Session) {
sessions.add((Session) _session);
}
}
return sessions;
}
/*
* (non-Javadoc)
*
* @see
* org.apache.shiro.session.mgt.eis.AbstractSessionDAO#doCreate(org.apache.
* shiro.session.Session)
*/
@Override
protected Serializable doCreate(Session session) {
Serializable sessionId = this.generateSessionId(session);
this.assignSessionId(session, sessionId);
update(session);
return sessionId;
}
/*
* (non-Javadoc)
*
* @see
* org.apache.shiro.session.mgt.eis.AbstractSessionDAO#doReadSession(java.io
* .Serializable)
*/
@Override
protected Session doReadSession(Serializable sessionId) {
String key = getSessionKey(sessionId);
Object sessionObj = _shiroRedisTemplate.opsForValue().get(key);
Session _session = null;
if (sessionObj instanceof Session) {
_session = (Session) sessionObj;
}
return _session;
}
}
shiro.xml
<!-- 凭证匹配器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="shiroDbRealm" />
<property name="cacheManager" ref="shiroRedisCacheManager" />
<!-- redis 缓存 -->
<property name="sessionManager" ref="defaultWebSessionManager" />
</bean>
<bean id="defaultWebSessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<!-- session存储的实现 -->
<property name="sessionDAO" ref="shiroRedisSessionDao" />
<!-- sessionIdCookie的实现,用于重写覆盖容器默认的JSESSIONID -->
<property name="sessionIdCookie" ref="shareSession" />
<!-- 设置全局会话超时时间,默认30分钟(1800000) -->
<property name="globalSessionTimeout" value="1800000" />
<!-- 是否在会话过期后会调用SessionDAO的delete方法删除会话 默认true -->
<property name="deleteInvalidSessions" value="true" />
<!-- 会话验证器调度时间 -->
<property name="sessionValidationInterval" value="1500000" />
<!-- 定时检查失效的session -->
<property name="sessionValidationSchedulerEnabled" value="true" />
</bean>
<!-- sessionIdCookie的实现,用于重写覆盖容器默认的JSESSIONID -->
<bean id="shareSession" class="org.apache.shiro.web.servlet.SimpleCookie">
<!-- cookie的name,对应的默认是 JSESSIONID -->
<constructor-arg name="name" value="SHAREJSESSIONID" />
<!-- jsessionId的path为 / 用于多个系统共享jsessionId -->
<property name="path" value="/" />
<property name="httpOnly" value="true"/>
</bean>
<bean id="shiroRedisCacheManager" class="ShiroRedisCacheManager">
<property name="shiroRedisTemplate" ref="shiroRedisTemplate"></property>
</bean>
<bean id="shiroRedisSessionDao" class="ShiroRedisSessionDao">
<property name="shiroRedisTemplate" ref="shiroRedisTemplate"></property>
</bean>
redis.xml
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.maxActive}" />
<property name="minIdle" value="${redis.minIdle}" />
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="jedisConnectionFactoryShiro"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="usePool" value="true" />
<property name="hostName" value="${redis.host}" />
<property name="port" value="${redis.port}" />
<property name="password" value="${redis.pass}" />
<property name="timeout" value="${redis.timeout}" />
<property name="database" value="${redis.shiroDb}" />
<constructor-arg index="0" ref="jedisPoolConfig" />
</bean>
<bean id="stringRedisSerializer"
class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean>
<bean id="jdkSerializationRedisSerializer"
class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean>
<bean id="shiroRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactoryShiro" />
<property name="keySerializer" ref="stringRedisSerializer"></property>
<property name="hashKeySerializer" ref="stringRedisSerializer"></property>
<property name="valueSerializer" ref="jdkSerializationRedisSerializer"></property>
<property name="hashValueSerializer" ref="jdkSerializationRedisSerializer"></property>
</bean>
Comments