通知
此博客运行在jpress系统上,如果你喜欢此博客模板,请加QQ群:1061691290(whimurmur模板/jpress插件),免费下载使用

尚硅谷shiro框架学习 会话管理

5010人浏览 / 0人评论 | 作者:whisper  | 分类: shiro  | 标签: 框架  | 

作者:whisper

链接:http://proprogrammar.com:443/article/113

声明:请尊重原作者的劳动,如需转载请注明出处


     Shiro 提供了完整的企业级会话管理功能,不依赖于底层容器(如web容器tomcat),不管 JavaSE 还是 JavaEE 环境都可以使用,提供了会话管理、会话事件监听、会话存储/持久化、容器无关的集群、失效/过期支持、对Web 的透明支持、 SSO 单点登录的支持等特性。

     会话相关的 API

     Subject.getSession():即可获取会话;其等价于Subject.getSession(true),即如果当前没有创建 Session 对象会创建
一个;Subject.getSession(false),如果当前没有创建 Session 则返回null
    session.getId():获取当前会话的唯一标识
    session.getHost():获取当前Subject的主机地址
    session.getTimeout() & session.setTimeout(毫秒):获取/设置当前Session的过期时间
    session.getStartTimestamp() & session.getLastAccessTime():获取会话的启动时间及最后访问时间;如果是 JavaSE 应用需要自己定期调用 session.touch() 去更新最后访问时间;如果是 Web 应用,每次进入 ShiroFilter 都会自动调用 session.touch() 来更新最后访问时间。
     session.touch() & session.stop():更新会话最后访问时间及销毁会话;当Subject.logout()时会自动调用 stop 方法
来销毁会话。如果在web中,调用 HttpSession. invalidate()也会自动调用Shiro Session.stop 方法进行销毁Shiro 的会话

     session.setAttribute(key, val) &session.getAttribute(key) &session.removeAttribute(key):设置/获取/删除会话属性;在整个会话范围内都可以对这些属性进行操作

    会话监听器

     会话监听器用于监听会话创建、过期及停止事件,类似于HttpSessionListener

    注意:shiro的session和HttpSession可以互相操作,如下图,controller层shiro的session设置了值,httpSession来读取,同时在service层,shiro的session读取httpSession的内容

    结果如下,可以看到,都读取到了

    SessionDao

    可以将Session持久化到数据库

    继承关系

    AbstractSessionDAO 提供了 SessionDAO 的基础实现,如生成会话ID等
    CachingSessionDAO 提供了对开发者透明的会话缓存的功能,需要设置相应的 CacheManager
    MemorySessionDAO 直接在内存中进行会话维护
    EnterpriseCacheSessionDAO 提供了缓存功能的会话维护,默认情况下使用 MapCache 实现,内部使用ConcurrentHashMap 保存缓存的会话。

    配置示例,其中sessionManager要配置给SecurityManager

    数据表



    sessionDAO的实现,实现了增删改查

package com.atguigu.shiro.realms;

import java.io.Serializable;
import java.util.List;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.ValidatingSession;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;

public class MySessionDao extends EnterpriseCacheSessionDAO {

	@Autowired
	private JdbcTemplate jdbcTemplate = null;

	@Override
	protected Serializable doCreate(Session session) {
		Serializable sessionId = generateSessionId(session);
		assignSessionId(session, sessionId);
		String sql = "insert into sessions(id, session) values(?,?)";
		jdbcTemplate.update(sql, sessionId,
				SerializableUtils.serialize(session));
		return session.getId();
	}

	@Override
	protected Session doReadSession(Serializable sessionId) {
		String sql = "select session from sessions where id=?";
		List<String> sessionStrList = jdbcTemplate.queryForList(sql,
				String.class, sessionId);
		if (sessionStrList.size() == 0)
			return null;
		return SerializableUtils.deserialize(sessionStrList.get(0));
	}
	
	@Override
	protected void doUpdate(Session session) {
		if (session instanceof ValidatingSession
				&& !((ValidatingSession) session).isValid()) {
			return; 
		}
		String sql = "update sessions set session=? where id=?";
		jdbcTemplate.update(sql, SerializableUtils.serialize(session),
				session.getId());
	}

	@Override
	protected void doDelete(Session session) {
		String sql = "delete from sessions where id=?";
		jdbcTemplate.update(sql, session.getId());
	}
}

   工具类SerializableUtils的实现

package com.atguigu.shiro.realms;

import org.apache.shiro.codec.Base64;
import org.apache.shiro.session.Session;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializableUtils {

	public static String serialize(Session session) {
		try {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(bos);
			oos.writeObject(session);
			return Base64.encodeToString(bos.toByteArray());
		} catch (Exception e) {
			throw new RuntimeException("serialize session error", e);
		}
	}

	public static Session deserialize(String sessionStr) {
		try {
			ByteArrayInputStream bis = new ByteArrayInputStream(
					Base64.decode(sessionStr));
			ObjectInputStream ois = new ObjectInputStream(bis);
			return (Session) ois.readObject();
		} catch (Exception e) {
			throw new RuntimeException("deserialize session error", e);
		}
	}
	
}

    会话验证

     Shiro 提供了会话验证调度器,用于定期的验证会话是否已过期,如果过期将停止会话
    出于性能考虑,一般情况下都是获取会话时来验证会话是否过期并停止会话的;但是如在 web 环境中,如果用户不主动退出是不知道会话是否过期的,因此需要定期的检测会话是否过期,Shiro 提供了会话验证调度器:SessionValidationScheduler
    Shiro 也提供了使用Quartz会话验证调度器:QuartzSessionValidationScheduler


亲爱的读者:有时间可以点赞评论一下

点赞(0) 打赏

全部评论

还没有评论!