Shiro + SSM(框架) + Freemarker(jsp)讲解的权限控制Demo,还不赶快去下载?
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;
@Override
public 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");
}
}
@Override
public 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");
}
}
@Override
public 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;
}
@Override
public 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;
}
@Override
public void update(Session session) throws UnknownSessionException {
getShiroSessionRepository().saveSession(session);
}
@Override
public 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);
}
@Override
public Collection<Session> getActiveSessions() {
return getShiroSessionRepository().getAllSessions();
}
@Override
protected Serializable doCreate(Session session) {
Serializable sessionId = this.generateSessionId(session);
this.assignSessionId(session, sessionId);
getShiroSessionRepository().saveSession(session);
return sessionId;
}
@Override
protected Session doReadSession(Serializable sessionId) {
return getShiroSessionRepository().getSession(sessionId);
} }
这样基本就OK了, Redis 配置请看前面的博客。因为我们是使用同一个 Redis ,所以 Session 是共享的。