Shiro + SSM(框架) + Freemarker(jsp)讲解的权限控制Demo,还不赶快去下载?
【转】http://www.sojson.com/blog/137.html
Shiro 我们通过重写AbstractSessionDAO ,来实现 Session 共享。再重写 Session 的时候(其实也不算重写),因为和HttpSession 没有任何实现或者继承关系。
Session 的每个回话的ID 生成器,我们用JavaUuidSessionIdGenerator (UUID 规则)。
<!-- 会话Session ID生成器 --><bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/>
Session 的创建、获取、删除
<!-- session 创建、删除、查询 --><bean id="jedisShiroSessionRepository" class="com.sojson.core.shiro.cache.JedisShiroSessionRepository" ><property name="jedisManager" ref="jedisManager"/></bean>
Session 的监听生命周期
<!-- custom shiro session listener --><bean id="customShiroSessionDAO" class="com.sojson.core.shiro.CustomShiroSessionDAO"><property name="shiroSessionRepository" ref="jedisShiroSessionRepository"/><property name="sessionIdGenerator" ref="sessionIdGenerator"/></bean>
Session 定时管理器(有效期)
<!-- 会话验证调度器 --><bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler"><property name="interval" value="${session.validate.timespan}"/><!--检测时间间距,默认是60分钟--><property name="sessionManager" ref="sessionManager"/></bean>
<!-- 会话Cookie模板 --><bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie"><!--cookie的name,我故意取名叫xxxxbaidu --><constructor-arg value="v_v-s-baidu"/><property name="httpOnly" value="true"/><!--cookie的有效时间 --><property name="maxAge" value="-1"/><!-- 配置存储Session Cookie的domain为 一级域名 --><property name="domain" value=".itboy.net"/></bean>
<!-- Session Manager --><bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"><!-- 相隔多久检查一次session的有效性 --><property name="sessionValidationInterval" value="1800000"/><!-- session 有效时间为半小时 (毫秒单位)--><property name="globalSessionTimeout" value="1800000"/><property name="sessionDAO" ref="customShiroSessionDAO"/><!-- session 监听,可以多个。 --><property name="sessionListeners"><list><ref bean="customSessionListener"/></list></property><!-- 间隔多少时间检查,不配置是60分钟 --><property name="sessionValidationScheduler" ref="sessionValidationScheduler"/><!-- 是否开启 检测,默认开启 --><property name="sessionValidationSchedulerEnabled" value="true"/><!-- 是否删除无效的,默认也是开启 --><property name="deleteInvalidSessions" value="true"/><!-- 会话Cookie模板 --><property name="sessionIdCookie" ref="sessionIdCookie"/></bean>
Session 的创建、删除、查询 ,ShiroSessionRepository 接口定义。
package com.sojson.core.shiro.session;import org.apache.shiro.session.Session;import java.io.Serializable;import java.util.Collection;/*** custom shiro session manager interface** @author zhoubaicheng*/public interface ShiroSessionRepository {/*** 存储Session* @param session*/void saveSession(Session session);/*** 删除session* @param sessionId*/void deleteSession(Serializable sessionId);/*** 获取session* @param sessionId* @return*/Session getSession(Serializable sessionId);/*** 获取所有sessoin* @return*/Collection<Session> getAllSessions();}
Session 的创建、删除、查询实现。com.sojson.core.shiro.cache.JedisShiroSessionRepository
package com.sojson.core.shiro.cache;import java.io.Serializable;import java.util.Collection;import org.apache.log4j.Logger;import org.apache.shiro.session.Session;import com.sojson.common.utils.SerializeUtil;import com.sojson.core.shiro.session.ShiroSessionRepository;/*** Session 管理* @author sojson.com**/@SuppressWarnings("unchecked")public class JedisShiroSessionRepository implements ShiroSessionRepository {private static Logger logger = Logger.getLogger(JedisShiroSessionRepository.class);public static final String REDIS_SHIRO_SESSION = "sojson-shiro-session:";//这里有个小BUG,因为Redis使用序列化后,Key反序列化回来发现前面有一段乱码,解决的办法是存储缓存不序列化public static final String REDIS_SHIRO_ALL = "*sojson-shiro-session:*";private static final int SESSION_VAL_TIME_SPAN = 18000;private static final int DB_INDEX = 1;private JedisManager jedisManager;@Overridepublic void saveSession(Session session) {if (session == null || session.getId() == null)throw new NullPointerException("session is empty");try {byte[] key = SerializeUtil.serialize(buildRedisSessionKey(session.getId()));byte[] value = SerializeUtil.serialize(session);long sessionTimeOut = session.getTimeout() / 1000;Long expireTime = sessionTimeOut + SESSION_VAL_TIME_SPAN + (5 * 60);getJedisManager().saveValueByKey(DB_INDEX, key, value, expireTime.intValue());} catch (Exception e) {e.printStackTrace();System.out.println("save session error");}}@Overridepublic void deleteSession(Serializable id) {if (id == null) {throw new NullPointerException("session id is empty");}try {getJedisManager().deleteByKey(DB_INDEX,SerializeUtil.serialize(buildRedisSessionKey(id)));} catch (Exception e) {e.printStackTrace();System.out.println("delete session error");}}@Overridepublic Session getSession(Serializable id) {if (id == null)throw new NullPointerException("session id is empty");Session session = null;try {byte[] value = getJedisManager().getValueByKey(DB_INDEX, SerializeUtil.serialize(buildRedisSessionKey(id)));session = SerializeUtil.deserialize(value, Session.class);} catch (Exception e) {e.printStackTrace();System.out.println("get session error");}return session;}@Overridepublic Collection<Session> getAllSessions() {Collection<Session> sessions = null;try {sessions = getJedisManager().AllSession(DB_INDEX,REDIS_SHIRO_SESSION);} catch (Exception e) {logger.error("获取全部session异常");e.printStackTrace();}return sessions;}private String buildRedisSessionKey(Serializable sessionId) {return REDIS_SHIRO_SESSION + sessionId;}public JedisManager getJedisManager() {return jedisManager;}public void setJedisManager(JedisManager jedisManager) {this.jedisManager = jedisManager;}}
CustomShiroSessionDAO的继承实现
package com.sojson.core.shiro;import java.io.Serializable;import java.util.Collection;import org.apache.log4j.Logger;import org.apache.shiro.session.Session;import org.apache.shiro.session.UnknownSessionException;import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;import com.sojson.core.shiro.session.ShiroSessionRepository;public class CustomShiroSessionDAO extends AbstractSessionDAO{private static Logger logger = Logger.getLogger(CustomShiroSessionDAO.class);private ShiroSessionRepository shiroSessionRepository;public ShiroSessionRepository getShiroSessionRepository() {return shiroSessionRepository;}public void setShiroSessionRepository(ShiroSessionRepository shiroSessionRepository) {this.shiroSessionRepository = shiroSessionRepository;}@Overridepublic void update(Session session) throws UnknownSessionException {getShiroSessionRepository().saveSession(session);}@Overridepublic void delete(Session session) {if (session == null) {logger.error("session can not be null,delete failed");return;}Serializable id = session.getId();if (id != null)getShiroSessionRepository().deleteSession(id);}@Overridepublic Collection<Session> getActiveSessions() {return getShiroSessionRepository().getAllSessions();}@Overrideprotected Serializable doCreate(Session session) {Serializable sessionId = this.generateSessionId(session);this.assignSessionId(session, sessionId);getShiroSessionRepository().saveSession(session);return sessionId;}@Overrideprotected Session doReadSession(Serializable sessionId) {return getShiroSessionRepository().getSession(sessionId);} }
这样基本就OK了, Redis 配置请看前面的博客。因为我们是使用同一个 Redis ,所以 Session 是共享的。