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的过期时间。
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):删除会话属性。
二、会话监听器
会话监听器用于监听会话创建、过期及停止事件。
public class MySessionListener1 implements SessionListener {
@Override
public void onStart(Session session) { // 会话创建时触发
System.out.println("会话创建:" + session.getId());
}
@Override
public void onExpiration(Session session) { // 会话过期时触发
System.out.println("会话过期:" + session.getId());
}
@Override
public void onStop(Session session) { // 退出或会话过期时触发
System.out.println("会话停止:" + session.getId());
}
}
测试:
我们建议在Controller 层使用原生的 HttpSession。在传统的应用里面不能再 Service 层访问 HttpSession,这时我们就可以使用 Shiro 的Session。
1、 使用HttpSession给Session中放入属性key;
@Controller
@RequestMapping("/shiro")
public class ShiroHandler {
@Autowired
private ShiroService shiroService;
@RequiresRoles({"admin"})
@RequestMapping("/testShiroAnnotation")
public String testShiroAnnotation(HttpSession session){
session.setAttribute("key", "value12345");
shiroService.testMethod();
return "redirect:/list.jsp";
}
}
2、 在Service层获取Session中属性key的值;
public class ShiroService {
public void testMethod(){
System.out.println("testMethod, time: " + new Date());
Session session = SecurityUtils.getSubject().getSession();
Object val = session.getAttribute("key");
System.out.println("Service SessionVal: " + val);
}
}
三、SessionDao
AbstractSessionDAO 提供了 SessionDAO 的基础实现, 如生成会话ID等。
CachingSessionDAO 提供了对开发者透明的会话缓存的功能,需要设置相应的 CacheManager。
MemorySessionDAO 直接在内存中进行会话维护。
EnterpriseCacheSessionDAO 提供了缓存功能的会话维护,默认情况下使用 MapCache 实现,内部使用 ConcurrentHashMap 保存缓存的会话。
1、 在Spring配置文件中配置SessionManager;
<!-- 配置 SecurityManager -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="cacheManager" ref="cacheManager"/>
<property name="authenticator" ref="authenticator"></property>
<property name="realms">
<list>
<ref bean="jdbcRealm"/>
<ref bean="secondRealm"/>
</list>
</property>
<property name="sessionManager" ref="sessionManager"></property>
</bean>
2、 在ehcache.xml配置缓存;
<cache name="shiro-activeSessionCache"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
3、 在数据库中创建表sessions;
create table sessions (
id varchar(200),
sessionvarchar(2000),
constraint pk_sessions primarykey(id)
) charset=utf8 ENGINE=InnoDB;
4、 SessionDao;
5、 SerializableUtils;
四、会话验证
Shiro 提供了会话验证调度器,用于定期的验证会话是否已过期,如果过期将停止会话。
出于性能考虑,一般情况下都是获取会话时来验证会话是否过期并停止会话的;但是如在 web 环境中,如果用户不 主动退出是不知道会话是否过期的,因此需要定期的检测会话是否过期,Shiro 提供了会话验证调度器 SessionValidationScheduler。
Shiro 也提供了使用Quartz会话验证调度器: QuartzSessionValidationScheduler
版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址: