shiro 使用时候更改session存储在redis中使用ProtoStuff序列化

本文介绍了一种将Apache Shiro认证框架与Redis结合使用的实现方式。为了解决Shiro SimpleSession序列化问题,作者自定义了OssSession和OssSessionFactory,并通过RedisSessionDAO进行会话管理,实现了高效可靠的会话存储。

使用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一致,只是把字段属性该了xi
public 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;
	}

	
}





评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值