使用redis序列化session时,发现shiro原生的SimpleSession对象的字段属性是transient字段。用ProtoStuff序列化会报错,无奈重写会话和会话工厂类。
public class OssSessionFactory implements SessionFactory {
@Override
public Session createSession(SessionContext initData) {
if (initData != null) {
String host = initData.getHost();
if (host != null) {
return new OssSession(host);
}
}
return new OssSession();
}
}基本SimpleSession一致,只是把字段属性该了xipublic class OssSession implements ValidatingSession, Serializable {
private static final Logger log = LoggerFactory.getLogger(OssSession.class);
private static final long serialVersionUID = 1L;
protected static final long MILLIS_PER_SECOND = 1000;
protected static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;
protected static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;
protected static final String userKey = "user";
protected static final String roleKey = "roles";
protected static final String menuKey = "menus";
private String id;
private Date startTimestamp;
private Date stopTimestamp;
private Date lastAccessTime;
private long timeout;
private String host;
private Map<Object, Object> attributes;
public OssSession() {
this.timeout = DefaultSessionManager.DEFAULT_GLOBAL_SESSION_TIMEOUT;
this.startTimestamp = new Date();
this.lastAccessTime = this.startTimestamp;
}
public OssSession(String host) {
this();
this.host = host;
}
@Override
public Serializable getId() {
return id;
}
@Override
public Date getStartTimestamp() {
return startTimestamp;
}
@Override
public Date getLastAccessTime() {
return lastAccessTime;
}
@Override
public long getTimeout() throws InvalidSessionException {
return timeout;
}
@Override
public void setTimeout(long maxIdleTimeInMillis) throws InvalidSessionException {
this.timeout = maxIdleTimeInMillis;
}
@Override
public String getHost() {
return host;
}
@Override
public void touch() throws InvalidSessionException {
this.lastAccessTime = new Date();
}
@Override
public void stop() throws InvalidSessionException {
if (this.stopTimestamp == null) {
this.stopTimestamp = new Date();
}
}
private Map<Object, Object> getAttributesLazy() {
Map<Object, Object> attributes = getAttributes();
if (attributes == null) {
attributes = new HashMap<Object, Object>();
setAttributes(attributes);
}
return attributes;
}
public class RedisSessionDAO extends AbstractSessionDAO {
private int redisSessionTimeout=30*60;
private String REDIS_KEY_PREFIX = "up-lnk:oss:session:";
private RedisTemplate redisTemplate;
@Override
public void update(Session session) throws UnknownSessionException {
storeSession(session.getId(), session);
}
@Override
public void delete(Session session) {
if (session == null) {
throw new NullPointerException("session argument cannot be null.");
}
Serializable id = session.getId();
if (id != null) {
redisTemplate.del(getSessionId(id));
}
}
@Override
public Collection<Session> getActiveSessions() {
Set<Session> sessions = new HashSet<Session>();
Set<String> keys = redisTemplate.keys(this.REDIS_KEY_PREFIX + "*");
if (keys != null && keys.size() > 0) {
for (String key : keys) {
Session s = redisTemplate.getObject(key, OssSession.class);
sessions.add(s);
}
}
if (CollectionUtils.isEmpty(sessions)) {
return Collections.emptySet();
} else {
return Collections.unmodifiableCollection(sessions);
}
}
@Override
protected Serializable doCreate(Session session) {
Serializable sessionId = generateSessionId(session);
((OssSession) session).setId(sessionId.toString());
storeSession(sessionId, session);
return sessionId;
}
@Override
protected Session doReadSession(Serializable sessionId) {
Session session=null;
session=redisTemplate.getObject(getSessionId(sessionId), OssSession.class);
return session;
}
protected Session storeSession(Serializable id, Session session) {
if (id == null) {
throw new NullPointerException("id argument cannot be null.");
}
redisTemplate.cacheObject(getSessionId(id), session);
redisTemplate.expire(getSessionId(id), redisSessionTimeout);
return session;
}
private String getSessionId(Serializable id) {
if (id == null) {
throw new NullPointerException("id argument cannot be null.");
}
return this.REDIS_KEY_PREFIX + id.toString();
}
public RedisTemplate getRedisTemplate() {
return redisTemplate;
}
public void setRedisTemplate(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
public int getRedisSessionTimeout() {
return redisSessionTimeout;
}
public void setRedisSessionTimeout(int redisSessionTimeout) {
this.redisSessionTimeout = redisSessionTimeout;
}
}
本文介绍了一种将Apache Shiro认证框架与Redis结合使用的实现方式。为了解决Shiro SimpleSession序列化问题,作者自定义了OssSession和OssSessionFactory,并通过RedisSessionDAO进行会话管理,实现了高效可靠的会话存储。
1740

被折叠的 条评论
为什么被折叠?



