内容简介: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)咨询。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Collective Intelligence实战
阿拉克 / 2010-9 / 58.00元
《Collective Intelligence实战》内容简介:在互联网上,利用用户的集体智慧是成功的关键。集体智慧是一种新兴的编程技术,可让您从人们访问web和与web交互的过程中找到有价值的模式、发现这些访问者之间的关系和确定他们的个人偏好及习惯等。《collective Intelligence实战》首先介绍了集体智慧的原则和构建更具交互性网站的思想,然后通过示例开发了一个直接可用的基于Ja......一起来看看 《Collective Intelligence实战》 这本书的介绍吧!