内容简介:Shiro安全框架基于Redis的分布式集群方案
前段时间做了一个市场推广相关的项目,安全框架使用的是Shiro,缓存框架使用的是spring-data-redis。为了使用户7x24小时访问,决定把项目由单机升级为分布式部署架构。但是安全框架shiro只有单机存储的SessionDao,尽管Shrio有基于Ehcache-rmi的组播/广播实现,然而集群的分布往往是跨网段的,甚至是跨地域的,所以寻求新的方案。
运行环境
Nginx + Tomcat7(3台) + JDK1.7
项目架构图
项目实现
pom.xml引入配置(版本自行更换):
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.7.10.RELEASE</version> </dependency>
redis.properties配置:
#============================# #===== redis sttings ====# #============================# redis.host=127.0.0.1 redis.port=6379 redis.password=123456 #单位秒 redis.expire=1800 redis.timeout=2000 redis.usepool=true redis.database=1
spring-context-redis.xml配置:
<!-- redis 配置 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig" /> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="${redis.host}" /> <property name="port" value="${redis.port}" /> <property name="password" value="${redis.password}" /> <property name="timeout" value="${redis.timeout}" /> <property name="poolConfig" ref="jedisPoolConfig" /> <property name="usePool" value="true" /> </bean> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="jedisConnectionFactory" /> </bean>
RedisSessionDAO配置(重写 AbstractSessionDAO):
import java.io.Serializable; import java.util.Collection; import java.util.HashSet; import java.util.Set; import java.util.concurrent.TimeUnit; import org.apache.shiro.session.Session; import org.apache.shiro.session.UnknownSessionException; import org.apache.shiro.session.mgt.eis.AbstractSessionDAO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.core.RedisTemplate; /** * 重写 AbstractSessionDAO * 使用Redis缓存 * 创建者 张志朋 * 创建时间 2018年1月10日 */ public class RedisSessionDAO extends AbstractSessionDAO { private static Logger logger = LoggerFactory.getLogger(RedisSessionDAO.class); /** * shiro-redis的session对象前缀 */ private RedisTemplate<String, Object> redisTemplate; // 0 - never expire private int expire = 3600000; /** * The Redis key prefix for the sessions */ private String keyPrefix = "shiro_market_redis_session:"; @Override public void update(Session session) throws UnknownSessionException { this.saveSession(session); } /** * save session * @param session * @throws UnknownSessionException */ private void saveSession(Session session) throws UnknownSessionException{ if(session == null || session.getId() == null){ logger.error("session or session id is null"); return; } String key = session.getId().toString(); session.setTimeout(expire); redisTemplate.opsForValue().set(keyPrefix+key, session, expire, TimeUnit.MILLISECONDS); } @Override public void delete(Session session) { if(session == null || session.getId() == null){ logger.error("session or session id is null"); return; } redisTemplate.delete(keyPrefix+session.getId().toString()); } @Override public Collection<Session> getActiveSessions() { Set<Session> sessions = new HashSet<Session>(); Set<String> keys = redisTemplate.keys(this.keyPrefix + "*"); if(keys != null && keys.size()>0){ for(String key:keys){ Session s = (Session)redisTemplate.opsForValue().get(key); sessions.add(s); } } return sessions; } @Override protected Serializable doCreate(Session session) { Serializable sessionId = this.generateSessionId(session); this.assignSessionId(session, sessionId); this.saveSession(session); return sessionId; } @Override protected Session doReadSession(Serializable sessionId) { if(sessionId == null){ logger.error("session id is null"); return null; } Session s = (Session)redisTemplate.opsForValue().get(keyPrefix+sessionId); return s; } /** * Returns the Redis session keys * prefix. * @return The prefix */ public String getKeyPrefix() { return keyPrefix; } /** * Sets the Redis sessions key * prefix. * @param keyPrefix The prefix */ public void setKeyPrefix(String keyPrefix) { this.keyPrefix = keyPrefix; } public RedisTemplate<String, Object> getRedisTemplate() { return redisTemplate; } public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) { this.redisTemplate = redisTemplate; } }
spring-shiro.xml配置:
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <!-- 会话超时时间,单位:毫秒 20m=1200000ms, 30m=1800000ms, 60m=3600000ms--> <!-- 设置session过期时间为1小时(单位:毫秒),默认为30分钟 --> <!-- 如果设置 Redis缓存 此处不生效将 --> <property name="globalSessionTimeout" value="3600000"></property> <property name="sessionValidationSchedulerEnabled" value="true"></property> <property name="sessionIdUrlRewritingEnabled" value="false"></property> <!-- 注入 redisSessionDAO --> <property name="sessionDAO" ref="sessionDAO"/> </bean> <!-- redisSessionDAO --> <bean id="sessionDAO" class="com.acts.market.common.session.RedisSessionDAO"> <property name="redisTemplate" ref="redisTemplate" /> </bean>


作者:小柒
出处: https://blog.52itstyle.com
分享是快乐的,也见证了个人成长历程,文章大多都是工作经验总结以及平时学习积累,基于自身认知不足之处在所难免,也请大家指正,共同进步。
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出, 如有问题, 可邮件(345849402@qq.com)咨询。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Don't Make Me Think
Steve Krug / New Riders Press / 18 August, 2005 / $35.00
Five years and more than 100,000 copies after it was first published, it's hard to imagine anyone working in Web design who hasn't read Steve Krug's "instant classic" on Web usability, but people are ......一起来看看 《Don't Make Me Think》 这本书的介绍吧!