什么是会话
会话的主要作用是在用户使用程序的过程中识别用户的身份信息。从用户打开一个程序/访问一个网页,会话就建立起来,直到用户关闭程序,一次完整的会话就结束,每个会话都有一个唯一的身份标识(ID)。
获取当前会话信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@Test public void testSession(){ IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini"); SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("tom", "123"); try{ subject.login(token); //获取当前会话对象 Session session = subject.getSession(); //打印当前会话ID System.out.println(session.getId()); } catch (AuthenticationException e){ e.printStackTrace(); } } |
会话的建立与否,并不要求用户必须登录,也就是说,没有登录的用户也可以存在会话,例如常见的游客(guest)。
会话的启动和关闭
会话从程序启动的那一刻开始就会被创建起来,因此,会话并不需要我们手动去创建。当退出程序或者关闭浏览器,会话就会自动关闭。Session对象提供了stop()
方法来关闭会话,如果我们需要手动关闭一个会话,可以使用这个方法,然而,我们不会直接去调用这个stop方法,而是使用subject的logout()
方法来关闭会话,stop方法会在logout方法中被调用。
会话的更新
使用session的touch()方法更新会话,从touch()方法的源码可以看到,它的作用就是设置Session对象的lastAccessTime属性为当前时间。
会话的一些属性
会话中保存着一些常见的属性,例如会话的启动时间、会话的生存期限、会话最后一次访问的时间等等。
每一个属性设置都有一个方法获取或设置它们的值,如下:
- session.getTimeout()
- session.setTimeout(timeout) //毫秒为单位
- session.getStartTimestamp()
- session.getLastAccessTime()
通常,我们都会为会话添加一些自定义属性
- session.setAttribute(key, value)
- session.removeAttribute(key)
会话管理器
会话管理器顾名思义就是用来管理会话的,例如会话的创建、更新、超时、删除以及监视会话的状态:创建、过期和停止。
shiro提供了三个默认的会话管理器实现:
DefaultSessionManager:DefaultWebSecurityManager的默认会话管理器,用于非web环境。
ServletContainerSessionManager:DefaultWebSecurityManager默认使用的会话管理器,用于web环境;使用的是基于HttpSession的会话方式,而HttpSession依赖于Servlet容器。
DefaultWebSessionManager:shiro自己实现的会话方式,用于web环境,不依赖于Sevlet容器。
设置会话超时
可以设置会话的全局过期时间,也可以单独为每一个会话设置过期时间。
全局会话的过期时间使用会话管理器的globalSessionTimeout
属性设置。
单独设置每一个会话的过期时间则使用Session对象的setTimeout()方法
监听会话状态
前面说过,会话管理器可以监听会话的创建、过期和停止事件,实际上,这些功能由SessionListener
提供,存在于AbstractNativeSessionManager中一个泛型类型为SessionListener的集合里面。SessionListener提供了三个需要实现的方法:
- onStart(Session session)
- onExpiration(Session session)
- onStop(Session session)
如果不想三个方法都实现而只想实现其中一个,可以继承SessionListenerAdapter
类,它提供了SessionListener方法的空实现。
会话持久化
会话持久化由SessionDao接口提供支持,该接口提供了四个必须实现的方法
- Serializable create(Session session)
- Session readSession(Serializable sessionId)
- void update(Session session)
- void delete(Session session)
DefaultWebSessionManager
默认使用的SessionDao是MemorySessionDao
,但是在企业环境中如果有太多的session需要被缓存的时候,MemorySessionDao并不适用,原因在于过多的session很可能造成内存溢出。推荐的做法是继承CachingSessionDao
实现自己的持久化方式。CachingSessionDao类有四个抽象方法可以被实现:
- protected abstract Serializable doCreate(Session session)
- protected abstract Session doReadSession(Serializable sessionId)
- protected abstract void doUpdate(Session session)
- protected abstract void doDelete(Session session)
通过实现这4个方法,可以实现自己的session持久化方式。例如把session保存到文件中或从文件中取回session;也可以把session保存到数据库中。
需要注意的是,由于默认的会话管理器是ServletContainerSessionManager
,这个管理器并没有sessionDao属性,如果要使用sessionDao,需要把会话管理器设置为DefaultWebSessionManager
。
会话验证
会话验证用于检查会话是否已经过期。shiro中的会话验证由AbstractValidatingSessionManager
和ValidatingSessionManager
接口提供支持。会话验证默认是开启的,使用的会话验证调度器接口是SessionValidationScheduler,目前实现这个接口的类有ExecutorServiceSessionValidationScheduler
和QuartzSessionValidationScheduler
,后者需要导入shiro-quartz
依赖包。在debug模式下可以清楚看到这些默认配置:
转载请注明:Pure nonsense » shiro会话管理