目录
5.1 ehcache.xml (添加到main\resources目录下)
5.2 spring-ehcache.xml,shiro与ehcache整合(添加到main\resources目录下)
5.3 修改spring-shiro.xml文件,添加相关配置 (完整,可直接覆盖即可)

Shiro提供了完整的企业级会话管理功能,不依赖于底层容器(如Tomcat),不管是J2SE还是J2EE环境都可以使用,提供了会话管理,会话事件监听,会话存储/持久化,容器无关的集群,失效/过期支持,对Web的透明支持,SSO单点登录的支持等特性。所谓会话,即用户访问应用时保持的连接关系,在多次交互中应用能够识别出当前访问的用户是谁,且可以在多次交互中保存一些数据。如访问一些网站时登录成功后,网站可以记住用户,且在退出之前都可以识别当前用户是谁。
会话管理器管理着应用中所有 Subject 的会话的创建、维护、删除、失效、验证等工作。是Shiro 的核心组件,顶层组件SecurityManager直接继承了SessionManager,且提供了SessionsSecurityManager实现直接把会话管理委托给相应的SessionManager
1)DefaultSessionManager:使用的默认实现,用于JavaSE环境
2)ServletContainerSessionManager:使用的默认实现,用于Web环境,其直接使用Servlet容器的会话
3)DefaultWebSessionManager:用于Web环境的实现,可以替代ServletContainerSessionManager,自己维护着会话,直接废弃了Servlet容器的会话管理
SessionListener会话监听器用于监听会话创建、过期及停止事件。
实现方式:
1)实现SessionListener,必须实现所有方法
2)继承SessionListenerAdapter,重写指定方法
相关API:
1)onStart(Session session):监听会话创建事件
2)onStop(Session session):监听会话销毁事件
3)onExpiration(Session session):监听会话过期事件
Shiro提供SessionDAO用于会话的CRUD,即DAO(Data Access Object)模式实现。
1)AbstractSessionDAO:提供了SessionDAO的基础实现,如生成会话ID等
2)CachingSessionDAO:提供了对开发者透明的会话缓存的功能,需要设置相应的CacheManager
3)MemorySessionDAO:直接在内存中进行会话维护(默认方式)
4)EnterpriseCacheSessionDAO:提供了缓存功能的会话维护,默认情况下使用MapCache实现,内部使用ConcurrentHashMap保存缓存的会话。
相关API:
如DefaultSessionManager在创建完session后会调用该方法;
如保存到关系数据库/文件系统/NoSQL数据库;
即可以实现会话的持久化;返回会话ID;主要此处返回的ID.equals(session.getId());
Serializable create(Session session);
根据会话ID获取会话
Session readSession(Serializable sessionId) throws UnknownSessionException;
更新会话;如更新会话最后访问时间/停止会话/设置超时时间/设置移除属性等会调用
void update(Session session) throws UnknownSessionException;
删除会话;当会话过期/会话停止(如用户退出时)会调用
void delete(Session session);
获取当前所有活跃用户,如果用户量多此方法影响性能
CollectiongetActiveSessions();
1)Shiro提供了会话验证调度器,用于定期的验证会话是否已过期,如果过期将停止会话。
2)出于性能考虑,一般情况下都是获取会话的同时来验证会话是否过期并停止会话的;但是如果在Web环境中,如果用户不主动退出是不知道会话是否过期的,因此需要定义的检测会话是否过期,Shiro提供了会话验证调度器来定期检查会话是否过期,SessionValidationScheduler 。
3)Shrio也提供了使用Quartz会话验证调度器 QuartzSessionValidationScheduler 。
在没有使用缓存的情况下,我们每次发送请求都会调用一次doGetAuthorizationInfo方法来进 行用户的授权操作,但是我们知道,一个用户具有的权限一般不会频繁的修改,也就是每次 授权的内容都是一样的,所以我们希望在用户登录成功的第一次授权成功后将用户的权限保 存在缓存中,下一次请求授权的话就直接从缓存中获取,这样效率会更高一些
Ehcache是现在最流行的纯Java开源缓存框架,配置简单、结构清晰、功能强大。是Hibernate中默认CacheProvider。Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点。
1) 够快
Ehcache的发行有一段时长了,经过几年的努力和不计其数的性能测试,Ehcache终被设计于large, high concurrency systems.
2) 够简单
开发者提供的接口非常简单明了,从Ehcache的搭建到运用运行仅仅需要的是你宝贵的几分钟。其实很多开发者都不知道自己用在用Ehcache,Ehcache被广泛的运用于其他的开源项目
3) 够袖珍关于这点的特性,官方给了一个很可爱的名字small foot print ,一般Ehcache的发布版本不会到2M,V 2.2.3 才 668KB。
4) 够轻量
核心程序仅仅依赖slf4j这一个包,没有之一!
5) 好扩展
Ehcache提供了对大数据的内存和硬盘的存储,最近版本允许多实例、保存对象高灵活性、 提供LRU、LFU、FIFO淘汰算法,基础属性支持热配置、支持的插件多
6) 监听器
缓存管理器监听器 (CacheManagerListener)和 缓存监听器(CacheEvenListener),做一些统计或数据一致性广播挺好用的
7) 分布式缓存
从Ehcache 1.2开始,支持高性能的分布式缓存,兼具灵活性和扩展性
- "1.0" encoding="UTF-8"?>
-
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0modelVersion>
-
- <groupId>com.jmhgroupId>
- <artifactId>mybatis03artifactId>
- <version>1.0-SNAPSHOTversion>
- <packaging>warpackaging>
-
- <name>mybatis03 Maven Webappname>
-
- <url>http://www.example.comurl>
-
-
- <properties>
- <spring.version>5.0.2.RELEASEspring.version>
- <maven.compiler.source>1.8maven.compiler.source>
- <maven.compiler.target>1.8maven.compiler.target>
- <jackson.version>2.9.3jackson.version>
- <shiro.version>1.2.5shiro.version>
- <slf4j.version>1.7.7slf4j.version>
- <log4j2.version>2.9.1log4j2.version>
- properties>
-
- <dependencies>
-
-
-
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-coreartifactId>
- <version>${spring.version}version>
- dependency>
-
-
-
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-beansartifactId>
- <version>${spring.version}version>
- dependency>
-
-
-
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-contextartifactId>
- <version>${spring.version}version>
- dependency>
-
-
-
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-ormartifactId>
- <version>${spring.version}version>
- dependency>
-
-
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-txartifactId>
- <version>${spring.version}
- version>
- dependency>
-
-
-
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-aspectsartifactId>
- <version>${spring.version}version>
- dependency>
-
-
-
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-webartifactId>
- <version>${spring.version}version>
- dependency>
-
-
-
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-testartifactId>
- <version>${spring.version}version>
- dependency>
-
-
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-webmvcartifactId>
- <version>${spring.version}version>
- dependency>
-
-
- <dependency>
- <groupId>jstlgroupId>
- <artifactId>jstlartifactId>
- <version>1.2version>
- dependency>
- <dependency>
- <groupId>taglibsgroupId>
- <artifactId>standardartifactId>
- <version>1.1.2version>
- dependency>
-
-
- <dependency>
- <groupId>com.fasterxml.jackson.coregroupId>
- <artifactId>jackson-databindartifactId>
- <version>${jackson.version}version>
- <exclusions>
- <exclusion>
- <artifactId>jackson-annotationsartifactId>
- <groupId>com.fasterxml.jackson.coregroupId>
- exclusion>
- exclusions>
- dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.coregroupId>
- <artifactId>jackson-coreartifactId>
- <version>${jackson.version}version>
- dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.coregroupId>
- <artifactId>jackson-annotationsartifactId>
- <version>${jackson.version}version>
- dependency>
-
-
- <dependency>
- <groupId>commons-fileuploadgroupId>
- <artifactId>commons-fileuploadartifactId>
- <version>1.3.3version>
- dependency>
-
-
- <dependency>
- <groupId>org.hibernategroupId>
- <artifactId>hibernate-validatorartifactId>
- <version>6.0.7.Finalversion>
- dependency>
-
-
- <dependency>
- <groupId>junitgroupId>
- <artifactId>junitartifactId>
- <version>4.12version>
- <scope>testscope>
- dependency>
-
-
- <dependency>
- <groupId>javax.servletgroupId>
- <artifactId>javax.servlet-apiartifactId>
- <version>4.0.0version>
- <scope>providedscope>
- dependency>
-
-
-
- <dependency>
- <groupId>org.mybatisgroupId>
- <artifactId>mybatisartifactId>
- <version>3.4.5version>
- dependency>
-
-
-
- <dependency>
- <groupId>com.github.pagehelpergroupId>
- <artifactId>pagehelperartifactId>
- <version>5.1.2version>
- dependency>
-
-
-
- <dependency>
- <groupId>org.mybatisgroupId>
- <artifactId>mybatis-springartifactId>
- <version>1.3.1version>
- dependency>
-
-
- <dependency>
- <groupId>mysqlgroupId>
- <artifactId>mysql-connector-javaartifactId>
- <version>5.1.44version>
- dependency>
-
-
-
- <dependency>
- <groupId>org.apache.commonsgroupId>
- <artifactId>commons-dbcp2artifactId>
- <version>2.1.1version>
- dependency>
-
-
- <dependency>
- <groupId>org.apache.commonsgroupId>
- <artifactId>commons-pool2artifactId>
- <version>2.4.3version>
- dependency>
-
-
-
-
- <dependency>
- <groupId>org.slf4jgroupId>
- <artifactId>slf4j-apiartifactId>
- <version>${slf4j.version}version>
- dependency>
- <dependency>
- <groupId>org.slf4jgroupId>
- <artifactId>jcl-over-slf4jartifactId>
- <version>${slf4j.version}version>
- <scope>runtimescope>
- <exclusions>
- <exclusion>
- <artifactId>slf4j-apiartifactId>
- <groupId>org.slf4jgroupId>
- exclusion>
- exclusions>
- dependency>
-
- <dependency>
- <groupId>org.apache.logging.log4jgroupId>
- <artifactId>log4j-slf4j-implartifactId>
- <version>${log4j2.version}version>
- <exclusions>
- <exclusion>
- <artifactId>slf4j-apiartifactId>
- <groupId>org.slf4jgroupId>
- exclusion>
- exclusions>
- dependency>
-
-
- <dependency>
- <groupId>org.apache.logging.log4jgroupId>
- <artifactId>log4j-coreartifactId>
- <version>${log4j2.version}version>
- dependency>
- <dependency>
- <groupId>org.apache.logging.log4jgroupId>
- <artifactId>log4j-apiartifactId>
- <version>${log4j2.version}version>
- dependency>
-
- <dependency>
- <groupId>org.apache.logging.log4jgroupId>
- <artifactId>log4j-webartifactId>
- <version>${log4j2.version}version>
- dependency>
-
- <dependency>
- <groupId>com.lmaxgroupId>
- <artifactId>disruptorartifactId>
- <version>3.2.0version>
- dependency>
-
-
- <dependency>
- <groupId>org.projectlombokgroupId>
- <artifactId>lombokartifactId>
- <version>1.18.20version>
- <scope>providedscope>
- dependency>
-
-
-
- <dependency>
- <groupId>org.apache.shirogroupId>
- <artifactId>shiro-coreartifactId>
- <version>${shiro.version}version>
- dependency>
-
- <dependency>
- <groupId>org.apache.shirogroupId>
- <artifactId>shiro-webartifactId>
- <version>${shiro.version}version>
- dependency>
-
- <dependency>
- <groupId>org.apache.shirogroupId>
- <artifactId>shiro-springartifactId>
- <version>${shiro.version}version>
- dependency>
-
-
- <dependency>
- <groupId>net.sf.ehcachegroupId>
- <artifactId>ehcacheartifactId>
- <version>2.10.0version>
- dependency>
-
-
- <dependency>
- <groupId>org.apache.shirogroupId>
- <artifactId>shiro-ehcacheartifactId>
- <version>1.4.1version>
- dependency>
-
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-context-supportartifactId>
- <version>${spring.version}version>
- dependency>
-
- dependencies>
-
- <build>
- <finalName>shiro02finalName>
- <resources>
-
- <resource>
- <directory>src/main/javadirectory>
- <includes>
- <include>**/*.xmlinclude>
- includes>
- resource>
-
- <resource>
- <directory>src/main/resourcesdirectory>
- <includes>
- <include>jdbc.propertiesinclude>
- <include>*.xmlinclude>
- includes>
- resource>
- resources>
- <pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.mybatis.generatorgroupId>
- <artifactId>mybatis-generator-maven-pluginartifactId>
- <version>1.3.2version>
- <dependencies>
-
- <dependency>
- <groupId>mysqlgroupId>
- <artifactId>mysql-connector-javaartifactId>
- <version>5.1.44version>
- dependency>
- dependencies>
- <configuration>
- <overwrite>trueoverwrite>
- configuration>
- plugin>
- plugins>
- pluginManagement>
- build>
- project>
- "1.0" encoding="UTF-8"?>
- <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
- updateCheck="false">
-
-
-
- <diskStore path="java.io.tmpdir"/>
-
-
-
-
-
-
-
-
-
-
-
-
-
- <defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false"
- timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/>
-
-
-
- <cache name="stuCache" eternal="false" maxElementsInMemory="100"
- overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0"
- timeToLiveSeconds="300" memoryStoreEvictionPolicy="LRU"/>
- ehcache>
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
-
-
- <bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
- <property name="configLocation" value="classpath:ehcache.xml"/>
- <property name="shared" value="true"/>
- bean>
-
- <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
- <property name="cacheManager" ref="cacheManagerFactory"/>
- bean>
- beans>
<import resource="spring-ehcache.xml"/>
需要修改创建会话监听器的位置到你自己的那里(资源在下方已提供)
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
-
-
-
-
- <bean id="shiroRealm" class="com.jmh.shiro.utils.Realm">
-
- <property name="cachingEnabled" value="true"/>
-
- <property name="authorizationCachingEnabled" value="true"/>
-
- <property name="authorizationCacheName" value="shiroAuthzCache"/>
-
-
-
-
- <property name="credentialsMatcher">
- <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
-
- <property name="hashAlgorithmName" value="md5"/>
-
- <property name="hashIterations" value="1024"/>
-
- <property name="storedCredentialsHexEncoded" value="true"/>
- bean>
- property>
- bean>
-
-
- <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
- <property name="realm" ref="shiroRealm" />
-
- <property name="cacheManager" ref="cacheManager"/>
- bean>
-
-
- <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
-
- <property name="securityManager" ref="securityManager" />
-
- <property name="loginUrl" value="/home/index.shtml"/>
-
-
-
-
-
- <property name="filterChainDefinitions">
- <value>
-
-
-
-
- /user/login=anon
- /book/**=authc
- /common/**=authc
-
- value>
- property>
- bean>
-
-
- <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
-
-
-
- <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator">
- bean>
-
-
-
- <bean id="customSessionDao" class="org.apache.shiro.session.mgt.eis.MemorySessionDAO">
- <property name="sessionIdGenerator" ref="sessionIdGenerator"/>
- bean>
-
-
-
- <bean id="shiroSessionListener" class="com.jmh.shiro.utils.ShiroSessionListener"/>
-
-
-
- <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
-
- <constructor-arg value="shiro.session"/>
-
- <property name="maxAge" value="-1"/>
-
- <property name="httpOnly" value="true"/>
- bean>
-
-
-
- <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
-
- <property name="globalSessionTimeout" value="180000"/>
-
- <property name="sessionDAO" ref="customSessionDao"/>
-
- <property name="sessionValidationInterval" value="1800000"/>
-
-
-
-
-
- <property name="deleteInvalidSessions" value="true"/>
-
- <property name="sessionListeners">
- <list>
- <ref bean="shiroSessionListener"/>
- list>
- property>
-
- <property name="sessionIdCookie" ref="sessionIdCookie"/>
-
-
- bean>
-
- beans>
ShiroSessionListener
- package com.jmh.shiro.utils;
-
- import org.apache.shiro.session.Session;
- import org.apache.shiro.session.SessionListener;
-
- /**
- * SessionListener会话监听器用于监听会话创建、过期及停止事件。
- * 实现方式:
- * 1)实现SessionListener,必须实现所有方法
- * 2)继承SessionListenerAdapter,重写指定方法
- * 相关API:
- * 1)onStart(Session session):监听会话创建事件
- * 2)onStop(Session session):监听会话销毁事件
- * 3)onExpiration(Session session):监听会话过期事件
- */
- public class ShiroSessionListener implements SessionListener {
- @Override
- public void onStart(Session session) {
- System.out.println("监听会话创建事件" + session.getId());
- }
-
- @Override
- public void onStop(Session session) {
- System.out.println("监听会话销毁事件" + session.getId());
- }
-
- @Override
- public void onExpiration(Session session) {
- System.out.println("监听会话过期事件" + session.getId());
- }
- }
注:这里只开启了授权缓存,避免每次请求都要重新查询授权数据!!!