- 浏览: 157129 次
- 性别:
- 来自: 大连
文章分类
最新评论
-
eclipseakwolf:
很棒的文章
Shiro User Manual-Authentication -
xugangqiang:
very good
Java Concurrent Programming (1) -
jlcon:
是不是AbstractShiroTest还需要继承EasyMo ...
Shiro User Manual-Testing -
jlcon:
createNiceMock这个EasyMockSupport ...
Shiro User Manual-Testing -
Technoboy:
53873039oycg 写道楼主:问下,你的那个dao接口的 ...
Shiro Example
1. Session Management
Shiro提供了安全框架所独有的特性:企业级session的解决方案。
1.1 Using Sessions
使用Subject获取Session:
和HttpServletRequest的API相似,Suject.getSession(boolean create)方法和HttpServletRequest.getSession(boolean create)有相同的逻辑:
a. 如果当前的Subject已经有Session,返回当前Session,参数boolean被忽略。
b. 如果当前的Subject没有Session,且参数boolean是true,创建新Session,并返回。
c. 如果当前的Subject没有Session,且参数boolean是false,不创建新Session,直接返回null。
有了Session,就可以进行任何操作,比如设置超时时间等。需要注意的是,此Session非HttpSession,也就是说,getSession 可以在非web环境下调用。
2. The SessionManager
SessionManager,是SecurityManager维护的核心组件,管理应用中所有的Session。默认的SecurityManager实现为DefaultSessionManager,它提供了企业级session管理的所有特性,像session验证,清理无效session等。可以通过securityManager的getSessionManager/setSessionManager方法获取和设置sessionManager,也可以使用INI文件配置:
需要注意的是,创建SessionManager相当复杂,Shiro默认提供的SessionManager可以满足大部分应用的需求。如果在web应用中,需要使用其他SessionManager实现。
2.1 Session Timeout
默认session的超时时间为30分钟,可以使用globalSessionTimeout设置一个全局的session超时时间。比如设置session超时时间为1小时:
2.2 Per-Session Timeout
globalSessionTimeout的设置是全局的,即对所有的session有效。也可以对单独session设置超时时间,使用session的timeout属性即可,单位也是毫秒。
2.3 Session Listeners
Shiro支持SessionListener的概念以允许你监听Session事件。可以通过实现SessionListener接口或继承SessionListenerAdapter类,然后设置SessionManager的sessionListeners属性即可,可以配置一或多个监听器:
需要注意的是,任何一个session事件的发生都会触发SessionListeners。
2.4 Session Storage
Session的创建和更新,需要将其内部的数据保存到"仓库里",session失效,也需要从"仓库里"删除其内部数据。SessionManager的实现中,会委托SessionDAO组件进行"仓库"的CRUD操作。
可以自定义SessionDAO实现,将session数据存储在内存,文件系统,关系型数据库,NoSQL数据库,或任何其他地方(上面所说仓库,即指存储的位置),然后配置到SessionManager的属性里即可:
以下是需要注意的地方:
配置的securityManager.sessionManager.sessionDAO = $sessionDAO,只有在使用Shiro自带的session管理器时才起作用。在web环境下,应用会使用Servlet容器的session管理器,而导致配置的SessionDAO无效。如果想在web应用中使用SessionDAO,先配置Shiro自带的session管理器:
Shiro自带的session管理器将session存储在内存里。这不适用于生产环境。
2.5 EHCache SessionDAO
如果不想实现自己的SessionDAO,推荐使用EHCache。EHCache将session信息存储在内存里,当内存达到极限时,会转存到磁盘。这样保证了在生产环境下,不会出现session丢失的现象。EHCache还可以缓存认证和授权的信息。如果想不依赖容器做session的集群,EHCache也是一个很好的选择。在EHCache基础上加入Terracotta,即可实现与容器无关的session集群缓存。使用EHCache很简单,首先需要保证classpath里有shiro-ehcache-<version>.jar,在INI中配置:
最后一行,securityManager.cacheManager = $cacheManager,配置了Shiro需要的CacheManager。由于EnterpriseCacheSessionDAO实现了CacheManagerAware接口,CacheManager会自动传入SessionDAO里。当SessionManager让EnterpriseCacheSessionDAO存储一个Session时,它将使用EHCache去存储session信息。
2.6 EHCache Session Cache Configuration
默认情况下,Shiro使用指定的ehcache.xml进行session缓存的配置。查看默认的ehcache.xml文件:
如果想改变缓存的配置,需要定义相同的缓存键(cache entry)以满足Shiro的需求。也可以根据需求改变maxElementsInMemory的值。需要注意的是,至少要保证以下两个属性存在且不能更改:
a. overflowToDisk="true" 这个属性保证了,当程序吃光内存时,sessions被保存到磁盘。
b. eternal="true" 这个属性保证了缓存键(cache entry,即Session实例)永不过期,且不能被缓存自动删除。这个属性非常重要,因为Shiro的内部验证是基于一个定时程序,如果关闭这个属性,缓存可能会在Shiro不知的情形下清除无用的session,导致验证出现问题。
2.7 EHCache Session Cache Name
默认情况下,EnterpriseCacheSessionDAO会使用配置在ehcache.xml中缓存名为shiro-activeSessionCache的CacheManager。如果想改为其他键名,只需要保证ehcache.xml中的缓存名与INI文件中配置的相同即可:
2.8 Custom Session IDs
默认的SessionDAO实现使用外部SessionIdGenerator组件产生Session ID。JavaUuidSessionIdGenerator为默认SessionIdGenerator的实现,使用UUIDs产生一个字符串格式的ID,它适用于生产环境。也可以通过实现SessionIdGenerator接口自定义session id的生成策略,然后配置到SessionDAO里即可:
2.9 Session Validation & Scheduling
Session必须有效,无效的session会被删除。这保证了,随着时间的持久,存储空间不会被占满,且session不会被重用。由于性能的原因,只有在判断session是否过期或失效时才会被验证,这意味着,如果没有周期性的验证,session orphans(指僵尸session,下面会解释)将占满存储空间。一个普通的情形可以描述僵尸session:比如,一个用户登录一个系统,session被创建。如果用户没有注销而直接关闭浏览器,session还保存在服务器的存储空间里。SessionManager无法知道这个用户已经不在使用浏览器,那么这个session就无法被再次使用了,就变为僵尸session了。
如果不定期的清理僵尸session,它将占满存储空间。为了防止僵尸session占满空间,SessionManager的实现提供了SessionValidationScheduler的支持。SessionValidationScheduler负责周期性的验证session以达到清除僵尸session目的。
2.10 Default SessionValidationScheduler
SessionValidationScheduler的默认实现ExecutorServiceSessionValidationScheduler支持所有的环境,它使用JDK的ScheduledExecutorService去控制验证的频率。默认情况下,一小时验证一次。可以通过配置一个新的ExecutorServiceSessionValidationScheduler来改变验证的间隔,单位是毫秒:
2.11 Custom SessionValidationScheduler
也可以自定义SessionValidationScheduler实现,然后配置到SessionManager里即可:
2.12 Disabling Session Validation
某些情况下,想关闭周期性验证session的功能,因为已在程序外控制了session的验证(比如通过企业级缓存的实时功能去清理过期的session,或使用自定义任务去验证),这种情况下,就需要关闭它:
这只是关闭了Shiro周期性对session验证的功能,当session信息从存储空间取出时,依旧先执行验证操作。
2.13 Invalid Session Deletion
正如上面我们所说,周期性验证session的目的就是删除那些无效的session。默认情况下,只要Shiro检测到有无效的session,它就调用SessionDAO.delete(session)方法试图从存储空间删除这个session。这是保证应用的存储空间不被耗尽的最佳实践。然而,有些应用不想Shiro自动删除session。比如,应用程序提供了SessionDAO用于查询存储空间,需要查询那些过期和失效的session(像在过去的一周,一个用户创建了多少sessions,或者用户平均创建session的数量以及类似报告性查询),这种情况下,你需要完全的关闭session的删除功能:
需要注意的是,如果你配置Shiro让其不删除失效的sessions,为了保证存储空间不被耗尽,你需要自己删除那些失效的session。还有一点值得注意,关闭session删除和关闭session周期性验证是不一样的。
3. Session Clustering
让人振奋人心的是,Shiro自带的session支持session集群,且不依赖容器环境。也就是说,如果你使用Shiro自带的session并配置了session集群,可以在Jetty,Tomcat,Jboss,Geronimo或任何其他环境下发布。Shiro是如何做到的?由于Shiro的N层POJO结构,Session集群就像Session持久化那样简单。如果配置了带有集群功能的SessionDAO,SessionDAO就负责和集群应用进行交互。
3.1 Distributed Caches
分布式缓存,例如: Ehcache+Terracotta, GigaSpaces Oracle Coherence,和 Memcached以及大多数的缓存,已经解决了分布式数据的持久化问题。因此,在Shiro中配置session集群,就是简单的配置一下分布式缓存。需要注意的是,当使用分布式缓存进行session存储,需要保证以下两点中必须有一项为真:
a. 分布式缓存有集群级的内存供所有活跃的session。
b. 如果分布式缓存没有集群级的内存来保存所有活跃的session,必须支持磁盘溢出,以防止session丢失。
不能保证其中的一点,就会出现session丢失问题。
3.2 EnterpriseCacheSessionDAO
Shiro提供了可以将数据持久化到分布式缓存的SessionDAO实现-EnterpriseCacheSessionDAO,只需要把CacheManager或Cache配置到EnterpriseCacheSessionDAO里即可:
尽管可以向SessionDAO里注入Cache实例,但通常情况下,是配置CacheManager,因为CacheManager可以满足所有缓存的需求,只需将CacheManager中使用的缓存名字配置到EnterpriseCacheSessionDAO里即可:
注意到上面的配置有点奇怪么?我们没有配置sessionDAO使用哪个Cache或CacheManager,它是怎么发现缓存并使用它们的呢?Shiro在初始化SecurityManager时,它会检查SessionDAO是否实现了CacheManagerAware接口。如果实现,它就会自动使用配置的全局CacheManager。而EnterpriseCacheSessionDAO实现了CacheManagerAware接口,SecurityManager会把配置的cacheManager(securityManager.cacheManager = $cacheManager)通过参数的形式传给EnterpriseCacheSessionDAO的setCacheManager方法。运行时,如果EnterpriseCacheSessionDAO需要activeSessionsCache,它会在CacheManager中通过键-activeSessionsCache进行查找,得到Cache实例,并使用缓存。
3.3 Ehcache + Terracotta
一个众所周知的分布式缓存方案就是Ehcache + Terracotta。如果你对Terracotta + Ehcache的分布式很了解的话,Shiro这部分的配置就很简单。由于添加了Terracotta,需要在ehcache.xml文件中加入Terracotta的配置。以下这个配置经过测试,可以正确运行:
可以通过改变<terracottaConfig url="localhost:9510"/>将引用指向你的Terracotta服务器。还有一点需要主要,和之前的配置不一样,必须将diskPersistent和overflowToDisk属性设为false,因为true在集群环境下不支持。
将这部分内容保存到ehcache.xml后,放在classpath路径下,然后打开Terracotta+Ehcache配置:
需要记住,顺序很重要。通过把cacheManager配置在securityManager里,保证了所有之前配置的CacheManagerAware组件能够传入CacheManager。
4. Sessions and Subject State
a. Stateful Applications (Sessions allowed)
默认情况下,SecurityManager使用Session存储Subject的标识信息和认证状态,这有以下几种好处:
1. 所有的应用程序对服务的请求,调用都和session ID关联,这对于Shiro将用户和请求关联十分重要。比如,通过调用Subject.Builder获取其关联的Subject:
这对于web应用和开发远程调用框架或消息服务框架非常有用。
2. 任何在初始化请求"RememberMe"得到的标识都可以在第一次访问时保存到session里。这保证了Subject的remembered标识可以通过请求被保存而无需每次都反序列化或解码。比如,在web应用中,如果标识已存在session里,就无需每次请求时读取加密过的RememberMe cookie。这是一个不错的性能增强。
b. Stateless Applications (Sessionless)
对于大部分的应用来说,默认策略都可以满足,除了应用中有无状态的需求。好多无状态的架构不允许在请求时持久化状态。那么Subject状态就无法通过请求保存,这要求应用程序必须在其他地方保证Subject的状态。这种场景一般发生在,对每次请求、调用都需要进行验证时,比如很多无状态的应用通过强制进行HTTP的验证,让浏览器代替用户进行验证。
4.1 Disabling Subject State Session Storage
从Shiro的1.2及其以后版本,如果想关闭Subject的持久化,可以这样做:
这将使Shiro无法从每次的请求/调用中使用session存储subject的状态。这意味着,你每次请求都需要认证,Shiro才能知道当前的Subject是谁。
4.2 A Hybrid Approach
上面的配置:securityManager.subjectDAO.sessionStorageEvaluator.sessionStorageEnabled = false关闭了Shiro使用Session作为所有Subject存储的策略。假设存在某种情景,一些Subject的信息需要使用Session存储,而其他Subject不需要,怎么办呢?:
a. 也许和人相关的Subject需要使用Session存储。
b. 也许和人无关的Subject不需要使用Session存储。
c. 也许所有和特殊类型或者对访问系统指定的位置使用session存储,其他的不需要。
如果你需要混合的使用session存储策略,,可以实现SessionStorageEvaluator接口。
4.3 SessionStorageEvaluator
如果你想准确的控制哪些Subject需要他们的状态持久化到Session,可以实现SessionStorageEvaluator接口,这个接口只有一个方法:
4.4 Subject Inspection
当实现了SessionStorageEvaluator接口的isSessionStorageEnabled(subject)方法,可以对subject进行任何的操作,不过和应用环境相关的Subject才是最有用的。比如,在web应用中,如果数据必须基于ServletRequest存储,可以获取request或response,转换Subject实例(以为运行时Subject实例就为WebSubject实例),就会获取HttpServletRequest:
4.5 Configuration
实现了SessionStorageEvaluator接口,然后进行如下配置:
4.6 Web Applications
通常web应用希望每个请求可以容易地启用或禁用会话的创建,而不管哪个Subject 正在执行请求。这在支持REST,消息服务或RMI构架上起到很好的效果。比如,也许正常的终端用户允许创建和使用session,但是远程的API客户端使用REST或SOAP,没有session的概念。为了支持这种混合的/每请求的功能,Shiro将noSessionCreation过滤器添加到了默认的过滤器池中。这个过滤器可以防止新session的创建,以达到无状态的调用。在INI文件的[urls]部分,显式的在其他过滤器前定义,以确保session不被使用:
这个过滤器允许session使用当前的session,但不允许在过滤器请求范围内创建新session。也就是说,在一个没有存在session的request或subject内,下面任意四个方法的调用都将自动触发DisabledSessionException:
a. httpServletRequest.getSession()
b. httpServletRequest.getSession(true)
c. subject.getSession()
d. subject.getSession(true)
如果一个Subject在访问由noSessionCreation保护的url前已经有session存在,上面四个方法将正常执行。最后,在所有情况下,下面这两个方法都可以执行:
a. httpServletRequest.getSession(false)
b. subject.getSession(false)
Shiro提供了安全框架所独有的特性:企业级session的解决方案。
1.1 Using Sessions
使用Subject获取Session:
Subject currentUser = SecurityUtils.getSubject(); Session session = currentUser.getSession(); session.setAttribute( "someKey", someValue);
和HttpServletRequest的API相似,Suject.getSession(boolean create)方法和HttpServletRequest.getSession(boolean create)有相同的逻辑:
a. 如果当前的Subject已经有Session,返回当前Session,参数boolean被忽略。
b. 如果当前的Subject没有Session,且参数boolean是true,创建新Session,并返回。
c. 如果当前的Subject没有Session,且参数boolean是false,不创建新Session,直接返回null。
有了Session,就可以进行任何操作,比如设置超时时间等。需要注意的是,此Session非HttpSession,也就是说,getSession 可以在非web环境下调用。
2. The SessionManager
SessionManager,是SecurityManager维护的核心组件,管理应用中所有的Session。默认的SecurityManager实现为DefaultSessionManager,它提供了企业级session管理的所有特性,像session验证,清理无效session等。可以通过securityManager的getSessionManager/setSessionManager方法获取和设置sessionManager,也可以使用INI文件配置:
[main] ... sessionManager = com.foo.my.SessionManagerImplementation securityManager.sessionManager = $sessionManager
需要注意的是,创建SessionManager相当复杂,Shiro默认提供的SessionManager可以满足大部分应用的需求。如果在web应用中,需要使用其他SessionManager实现。
2.1 Session Timeout
默认session的超时时间为30分钟,可以使用globalSessionTimeout设置一个全局的session超时时间。比如设置session超时时间为1小时:
main] ... # 3,600,000 milliseconds = 1 hour securityManager.sessionManager.globalSessionTimeout = 3600000
2.2 Per-Session Timeout
globalSessionTimeout的设置是全局的,即对所有的session有效。也可以对单独session设置超时时间,使用session的timeout属性即可,单位也是毫秒。
2.3 Session Listeners
Shiro支持SessionListener的概念以允许你监听Session事件。可以通过实现SessionListener接口或继承SessionListenerAdapter类,然后设置SessionManager的sessionListeners属性即可,可以配置一或多个监听器:
[main] ... aSessionListener = com.foo.my.SessionListener anotherSessionListener = com.foo.my.OtherSessionListener securityManager.sessionManager.sessionListeners = $aSessionListener, $anotherSessionListener, etc.
需要注意的是,任何一个session事件的发生都会触发SessionListeners。
2.4 Session Storage
Session的创建和更新,需要将其内部的数据保存到"仓库里",session失效,也需要从"仓库里"删除其内部数据。SessionManager的实现中,会委托SessionDAO组件进行"仓库"的CRUD操作。
可以自定义SessionDAO实现,将session数据存储在内存,文件系统,关系型数据库,NoSQL数据库,或任何其他地方(上面所说仓库,即指存储的位置),然后配置到SessionManager的属性里即可:
[main] ... sessionDAO = com.foo.my.SessionDAO securityManager.sessionManager.sessionDAO = $sessionDAO
以下是需要注意的地方:
配置的securityManager.sessionManager.sessionDAO = $sessionDAO,只有在使用Shiro自带的session管理器时才起作用。在web环境下,应用会使用Servlet容器的session管理器,而导致配置的SessionDAO无效。如果想在web应用中使用SessionDAO,先配置Shiro自带的session管理器:
[main] ... sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager securityManager.sessionManager = $sessionManager # Configure a SessionDAO and then set it: securityManager.sessionManager.sessionDAO = $sessionDAO
Shiro自带的session管理器将session存储在内存里。这不适用于生产环境。
2.5 EHCache SessionDAO
如果不想实现自己的SessionDAO,推荐使用EHCache。EHCache将session信息存储在内存里,当内存达到极限时,会转存到磁盘。这样保证了在生产环境下,不会出现session丢失的现象。EHCache还可以缓存认证和授权的信息。如果想不依赖容器做session的集群,EHCache也是一个很好的选择。在EHCache基础上加入Terracotta,即可实现与容器无关的session集群缓存。使用EHCache很简单,首先需要保证classpath里有shiro-ehcache-<version>.jar,在INI中配置:
[main] sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO securityManager.sessionManager.sessionDAO = $sessionDAO cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager securityManager.cacheManager = $cacheManager
最后一行,securityManager.cacheManager = $cacheManager,配置了Shiro需要的CacheManager。由于EnterpriseCacheSessionDAO实现了CacheManagerAware接口,CacheManager会自动传入SessionDAO里。当SessionManager让EnterpriseCacheSessionDAO存储一个Session时,它将使用EHCache去存储session信息。
2.6 EHCache Session Cache Configuration
默认情况下,Shiro使用指定的ehcache.xml进行session缓存的配置。查看默认的ehcache.xml文件:
<cache name="shiro-activeSessionCache" maxElementsInMemory="10000" overflowToDisk="true" eternal="true" timeToLiveSeconds="0" timeToIdleSeconds="0" diskPersistent="true" diskExpiryThreadIntervalSeconds="600"/>
如果想改变缓存的配置,需要定义相同的缓存键(cache entry)以满足Shiro的需求。也可以根据需求改变maxElementsInMemory的值。需要注意的是,至少要保证以下两个属性存在且不能更改:
a. overflowToDisk="true" 这个属性保证了,当程序吃光内存时,sessions被保存到磁盘。
b. eternal="true" 这个属性保证了缓存键(cache entry,即Session实例)永不过期,且不能被缓存自动删除。这个属性非常重要,因为Shiro的内部验证是基于一个定时程序,如果关闭这个属性,缓存可能会在Shiro不知的情形下清除无用的session,导致验证出现问题。
2.7 EHCache Session Cache Name
默认情况下,EnterpriseCacheSessionDAO会使用配置在ehcache.xml中缓存名为shiro-activeSessionCache的CacheManager。如果想改为其他键名,只需要保证ehcache.xml中的缓存名与INI文件中配置的相同即可:
[main] ... sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO sessionDAO.activeSessionsCacheName = myname ...
2.8 Custom Session IDs
默认的SessionDAO实现使用外部SessionIdGenerator组件产生Session ID。JavaUuidSessionIdGenerator为默认SessionIdGenerator的实现,使用UUIDs产生一个字符串格式的ID,它适用于生产环境。也可以通过实现SessionIdGenerator接口自定义session id的生成策略,然后配置到SessionDAO里即可:
[main] ... sessionIdGenerator = com.my.session.SessionIdGenerator securityManager.sessionManager.sessionDAO.sessionIdGenerator = $sessionIdGenerator
2.9 Session Validation & Scheduling
Session必须有效,无效的session会被删除。这保证了,随着时间的持久,存储空间不会被占满,且session不会被重用。由于性能的原因,只有在判断session是否过期或失效时才会被验证,这意味着,如果没有周期性的验证,session orphans(指僵尸session,下面会解释)将占满存储空间。一个普通的情形可以描述僵尸session:比如,一个用户登录一个系统,session被创建。如果用户没有注销而直接关闭浏览器,session还保存在服务器的存储空间里。SessionManager无法知道这个用户已经不在使用浏览器,那么这个session就无法被再次使用了,就变为僵尸session了。
如果不定期的清理僵尸session,它将占满存储空间。为了防止僵尸session占满空间,SessionManager的实现提供了SessionValidationScheduler的支持。SessionValidationScheduler负责周期性的验证session以达到清除僵尸session目的。
2.10 Default SessionValidationScheduler
SessionValidationScheduler的默认实现ExecutorServiceSessionValidationScheduler支持所有的环境,它使用JDK的ScheduledExecutorService去控制验证的频率。默认情况下,一小时验证一次。可以通过配置一个新的ExecutorServiceSessionValidationScheduler来改变验证的间隔,单位是毫秒:
[main] ... sessionValidationScheduler = org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler # Default is 3,600,000 millis = 1 hour: sessionValidationScheduler.interval = 3600000 securityManager.sessionManager.sessionValidationScheduler = $sessionValidationScheduler
2.11 Custom SessionValidationScheduler
也可以自定义SessionValidationScheduler实现,然后配置到SessionManager里即可:
[main] ... sessionValidationScheduler = com.foo.my.SessionValidationScheduler securityManager.sessionManager.sessionValidationScheduler = $sessionValidationScheduler
2.12 Disabling Session Validation
某些情况下,想关闭周期性验证session的功能,因为已在程序外控制了session的验证(比如通过企业级缓存的实时功能去清理过期的session,或使用自定义任务去验证),这种情况下,就需要关闭它:
[main] ... securityManager.sessionManager.sessionValidationSchedulerEnabled = false
这只是关闭了Shiro周期性对session验证的功能,当session信息从存储空间取出时,依旧先执行验证操作。
2.13 Invalid Session Deletion
正如上面我们所说,周期性验证session的目的就是删除那些无效的session。默认情况下,只要Shiro检测到有无效的session,它就调用SessionDAO.delete(session)方法试图从存储空间删除这个session。这是保证应用的存储空间不被耗尽的最佳实践。然而,有些应用不想Shiro自动删除session。比如,应用程序提供了SessionDAO用于查询存储空间,需要查询那些过期和失效的session(像在过去的一周,一个用户创建了多少sessions,或者用户平均创建session的数量以及类似报告性查询),这种情况下,你需要完全的关闭session的删除功能:
[main] ... securityManager.sessionManager.deleteInvalidSessions = false
需要注意的是,如果你配置Shiro让其不删除失效的sessions,为了保证存储空间不被耗尽,你需要自己删除那些失效的session。还有一点值得注意,关闭session删除和关闭session周期性验证是不一样的。
3. Session Clustering
让人振奋人心的是,Shiro自带的session支持session集群,且不依赖容器环境。也就是说,如果你使用Shiro自带的session并配置了session集群,可以在Jetty,Tomcat,Jboss,Geronimo或任何其他环境下发布。Shiro是如何做到的?由于Shiro的N层POJO结构,Session集群就像Session持久化那样简单。如果配置了带有集群功能的SessionDAO,SessionDAO就负责和集群应用进行交互。
3.1 Distributed Caches
分布式缓存,例如: Ehcache+Terracotta, GigaSpaces Oracle Coherence,和 Memcached以及大多数的缓存,已经解决了分布式数据的持久化问题。因此,在Shiro中配置session集群,就是简单的配置一下分布式缓存。需要注意的是,当使用分布式缓存进行session存储,需要保证以下两点中必须有一项为真:
a. 分布式缓存有集群级的内存供所有活跃的session。
b. 如果分布式缓存没有集群级的内存来保存所有活跃的session,必须支持磁盘溢出,以防止session丢失。
不能保证其中的一点,就会出现session丢失问题。
3.2 EnterpriseCacheSessionDAO
Shiro提供了可以将数据持久化到分布式缓存的SessionDAO实现-EnterpriseCacheSessionDAO,只需要把CacheManager或Cache配置到EnterpriseCacheSessionDAO里即可:
#This implementation would use your preferred distributed caching product's APIs: activeSessionCache = my.org.apache.shiro.cache.CacheImplementation sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO sessionDAO.activeSessionCache = $activeSessionCache securityManager.sessionManager.sessionDAO = $sessionDAO
尽管可以向SessionDAO里注入Cache实例,但通常情况下,是配置CacheManager,因为CacheManager可以满足所有缓存的需求,只需将CacheManager中使用的缓存名字配置到EnterpriseCacheSessionDAO里即可:
# This implementation would use your caching product's APIs: cacheManager = my.org.apache.shiro.cache.CacheManagerImplementation # Now configure the EnterpriseCacheSessionDAO and tell it what # cache in the CacheManager should be used to store active sessions: sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO # This is the default value. Change it if your CacheManager configured a different name: sessionDAO.activeSessionsCacheName = shiro-activeSessionsCache # Now have the native SessionManager use that DAO: securityManager.sessionManager.sessionDAO = $sessionDAO # Configure the above CacheManager on Shiro's SecurityManager # to use it for all of Shiro's caching needs: securityManager.cacheManager = $cacheManager
注意到上面的配置有点奇怪么?我们没有配置sessionDAO使用哪个Cache或CacheManager,它是怎么发现缓存并使用它们的呢?Shiro在初始化SecurityManager时,它会检查SessionDAO是否实现了CacheManagerAware接口。如果实现,它就会自动使用配置的全局CacheManager。而EnterpriseCacheSessionDAO实现了CacheManagerAware接口,SecurityManager会把配置的cacheManager(securityManager.cacheManager = $cacheManager)通过参数的形式传给EnterpriseCacheSessionDAO的setCacheManager方法。运行时,如果EnterpriseCacheSessionDAO需要activeSessionsCache,它会在CacheManager中通过键-activeSessionsCache进行查找,得到Cache实例,并使用缓存。
3.3 Ehcache + Terracotta
一个众所周知的分布式缓存方案就是Ehcache + Terracotta。如果你对Terracotta + Ehcache的分布式很了解的话,Shiro这部分的配置就很简单。由于添加了Terracotta,需要在ehcache.xml文件中加入Terracotta的配置。以下这个配置经过测试,可以正确运行:
<ehcache> <terracottaConfig url="localhost:9510"/> <diskStore path="java.io.tmpdir/shiro-ehcache"/> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="false" diskPersistent="false" diskExpiryThreadIntervalSeconds="120"> <terracotta/> </defaultCache> <cache name="shiro-activeSessionCache" maxElementsInMemory="10000" eternal="true" timeToLiveSeconds="0" timeToIdleSeconds="0" diskPersistent="false" overflowToDisk="false" diskExpiryThreadIntervalSeconds="600"> <terracotta/> </cache> <!-- Add more cache entries as desired, for example, Realm authc/authz caching: --> </ehcache>
可以通过改变<terracottaConfig url="localhost:9510"/>将引用指向你的Terracotta服务器。还有一点需要主要,和之前的配置不一样,必须将diskPersistent和overflowToDisk属性设为false,因为true在集群环境下不支持。
将这部分内容保存到ehcache.xml后,放在classpath路径下,然后打开Terracotta+Ehcache配置:
sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO # This name matches a cache name in ehcache.xml: sessionDAO.activeSessionsCacheName = shiro-activeSessionsCache securityManager.sessionManager.sessionDAO = $sessionDAO # Configure The EhCacheManager: cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager cacheManager.cacheManagerConfigFile = classpath:ehcache.xml # Configure the above CacheManager on Shiro's SecurityManager # to use it for all of Shiro's caching needs: securityManager.cacheManager = $cacheManager
需要记住,顺序很重要。通过把cacheManager配置在securityManager里,保证了所有之前配置的CacheManagerAware组件能够传入CacheManager。
4. Sessions and Subject State
a. Stateful Applications (Sessions allowed)
默认情况下,SecurityManager使用Session存储Subject的标识信息和认证状态,这有以下几种好处:
1. 所有的应用程序对服务的请求,调用都和session ID关联,这对于Shiro将用户和请求关联十分重要。比如,通过调用Subject.Builder获取其关联的Subject:
Serializable sessionId = //get from the inbound request or remote method invocation payload Subject requestSubject = new Subject.Builder().sessionId(sessionId).buildSubject();
这对于web应用和开发远程调用框架或消息服务框架非常有用。
2. 任何在初始化请求"RememberMe"得到的标识都可以在第一次访问时保存到session里。这保证了Subject的remembered标识可以通过请求被保存而无需每次都反序列化或解码。比如,在web应用中,如果标识已存在session里,就无需每次请求时读取加密过的RememberMe cookie。这是一个不错的性能增强。
b. Stateless Applications (Sessionless)
对于大部分的应用来说,默认策略都可以满足,除了应用中有无状态的需求。好多无状态的架构不允许在请求时持久化状态。那么Subject状态就无法通过请求保存,这要求应用程序必须在其他地方保证Subject的状态。这种场景一般发生在,对每次请求、调用都需要进行验证时,比如很多无状态的应用通过强制进行HTTP的验证,让浏览器代替用户进行验证。
4.1 Disabling Subject State Session Storage
从Shiro的1.2及其以后版本,如果想关闭Subject的持久化,可以这样做:
[main] ... securityManager.subjectDAO.sessionStorageEvaluator.sessionStorageEnabled = false ...
这将使Shiro无法从每次的请求/调用中使用session存储subject的状态。这意味着,你每次请求都需要认证,Shiro才能知道当前的Subject是谁。
4.2 A Hybrid Approach
上面的配置:securityManager.subjectDAO.sessionStorageEvaluator.sessionStorageEnabled = false关闭了Shiro使用Session作为所有Subject存储的策略。假设存在某种情景,一些Subject的信息需要使用Session存储,而其他Subject不需要,怎么办呢?:
a. 也许和人相关的Subject需要使用Session存储。
b. 也许和人无关的Subject不需要使用Session存储。
c. 也许所有和特殊类型或者对访问系统指定的位置使用session存储,其他的不需要。
如果你需要混合的使用session存储策略,,可以实现SessionStorageEvaluator接口。
4.3 SessionStorageEvaluator
如果你想准确的控制哪些Subject需要他们的状态持久化到Session,可以实现SessionStorageEvaluator接口,这个接口只有一个方法:
public interface SessionStorageEvaluator { public boolean isSessionStorageEnabled(Subject subject); }
4.4 Subject Inspection
当实现了SessionStorageEvaluator接口的isSessionStorageEnabled(subject)方法,可以对subject进行任何的操作,不过和应用环境相关的Subject才是最有用的。比如,在web应用中,如果数据必须基于ServletRequest存储,可以获取request或response,转换Subject实例(以为运行时Subject实例就为WebSubject实例),就会获取HttpServletRequest:
public boolean isSessionStorageEnabled(Subject subject) { boolean enabled = false; if (WebUtils.isWeb(Subject)) { HttpServletRequest request = WebUtils.getHttpRequest(subject); //set 'enabled' based on the current request. } else { //not a web request - maybe a RMI or daemon invocation? //set 'enabled' another way... } return enabled; }
4.5 Configuration
实现了SessionStorageEvaluator接口,然后进行如下配置:
[main] ... sessionStorageEvaluator = com.mycompany.shiro.subject.mgt.MySessionStorageEvaluator securityManager.subjectDAO.sessionStorageEvaluator = $sessionStorageEvaluator ...
4.6 Web Applications
通常web应用希望每个请求可以容易地启用或禁用会话的创建,而不管哪个Subject 正在执行请求。这在支持REST,消息服务或RMI构架上起到很好的效果。比如,也许正常的终端用户允许创建和使用session,但是远程的API客户端使用REST或SOAP,没有session的概念。为了支持这种混合的/每请求的功能,Shiro将noSessionCreation过滤器添加到了默认的过滤器池中。这个过滤器可以防止新session的创建,以达到无状态的调用。在INI文件的[urls]部分,显式的在其他过滤器前定义,以确保session不被使用:
[urls] ... /rest/** = noSessionCreation, authcBasic, ...
这个过滤器允许session使用当前的session,但不允许在过滤器请求范围内创建新session。也就是说,在一个没有存在session的request或subject内,下面任意四个方法的调用都将自动触发DisabledSessionException:
a. httpServletRequest.getSession()
b. httpServletRequest.getSession(true)
c. subject.getSession()
d. subject.getSession(true)
如果一个Subject在访问由noSessionCreation保护的url前已经有session存在,上面四个方法将正常执行。最后,在所有情况下,下面这两个方法都可以执行:
a. httpServletRequest.getSession(false)
b. subject.getSession(false)
发表评论
-
Shiro Filters
2013-05-06 14:07 30151. Overview 对于web应用 ... -
Shiro Example
2013-04-23 16:11 17451. 说明: maven项目,基于Spring3.1,My ... -
Shiro用户手册-中文版pdf
2013-04-21 19:47 2125Apache Shiro用户手册中文版。 -
Shiro User Manual-Custom Subjects
2013-04-18 11:03 20561. Custom Subject Instances Sh ... -
Shiro User Manual-Testing
2013-04-18 10:59 37031. Test Setup 创建的Subject实例,必须要 ... -
Shiro User Manual-Architecture
2013-04-16 11:02 12611. Overview Shiro的设计目标是通过直观而简易 ... -
Shiro User Manual-Tutorial
2013-04-16 10:52 22551. Your First Apache Shiro Appl ... -
Shiro User Manual-Introduction
2013-04-16 10:42 11861. What is Apache Shiro? Shiro ... -
Shiro User Manual-Command Line Hasher
2013-04-19 11:49 17891. Overview Shiro1.2及其以 ... -
Shiro User Manual-Configuration
2013-04-16 11:19 18801. Configuration Shiro可以 ... -
Shiro User Manual-Web Support
2013-04-18 10:41 27921. Configuration 将Shiro集成到web应 ... -
Shiro User Manual-Integrating Into Spring
2013-04-18 11:23 20911. Overview Shiro的JavaBeans兼容性 ... -
Shiro User Manual-Caching
2013-04-18 10:52 18031. Caching Shiro团队了解 ... -
Shiro User Manual-Realms
2013-04-17 11:54 19251. Realms Realm是可以访问应用系统中数据,例如 ... -
Shiro User Manual-Authorization-Permissions
2013-04-17 09:31 19881. Wildcard Permissions 为了 ... -
Shiro User Manual-Authorization
2013-04-17 09:22 23451. Authorization Authorizatio ... -
Shiro User Manual-Authentication
2013-04-16 11:28 33521.Authentication Authenticatio ...
相关推荐
shiro(shiro-all-1.8.0.jar)
赠送jar包:shiro-core-1.4.0.jar; 赠送原API文档:shiro-core-1.4.0-javadoc.jar; 赠送源代码:shiro-core-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-core-1.4.0.pom; 包含翻译后的API文档:shiro-core...
Apache Shiro是一个强大的Java安全框架,它提供了身份验证(Authentication)、授权(Authorization)以及会话管理(Session Management)等功能,广泛应用于各种类型的Java应用程序中。标题提到的"shiro-attack-...
赠送jar包:shiro-config-core-1.4.0.jar; 赠送原API文档:shiro-config-core-1.4.0-javadoc.jar; 赠送源代码:shiro-config-core-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-config-core-1.4.0.pom; ...
解决:升級1.7后附件...shiro-cas-1.7.0.jar shiro-core-1.7.0.jar shiro-ehcache-1.7.0.jar shiro-spring-1.7.0.jar shiro-web-1.7.0.jar CustomShiroFilterFactoryBean.java spring-context-shiro.xml 修改说明.txt
赠送jar包:shiro-ehcache-1.4.0.jar; 赠送原API文档:shiro-ehcache-1.4.0-javadoc.jar; 赠送源代码:shiro-ehcache-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-ehcache-1.4.0.pom; 包含翻译后的API文档...
shiro-all-1.7.1.jar,shiro-aspectj-1.7.1.jar,shiro-cache-1.7.1.jar,shiro-config-core-1.7.1.jar,shiro-config-ogdl-1.7.1.jar,shiro-core-1.7.1.jar,shiro-crypto-cipher-1.7.1.jar,shiro-crypto-core-1.7.1.jar...
赠送jar包:shiro-crypto-core-1.4.0.jar; 赠送原API文档:shiro-crypto-core-1.4.0-javadoc.jar; 赠送源代码:shiro-crypto-core-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-crypto-core-1.4.0.pom; ...
赠送jar包:shiro-crypto-cipher-1.4.0.jar; 赠送原API文档:shiro-crypto-cipher-1.4.0-javadoc.jar; 赠送源代码:shiro-crypto-cipher-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-crypto-cipher-1.4.0....
赠送jar包:shiro-crypto-core-1.4.0.jar; 赠送原API文档:shiro-crypto-core-1.4.0-javadoc.jar; 赠送源代码:shiro-crypto-core-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-crypto-core-1.4.0.pom; ...
在这个名为"shiro-redis-session-master"的项目中,开发者采用Redis作为Shiro的会话管理存储,以实现跨服务器的集群会话共享,从而提高系统的可扩展性和可用性。 **一、Shiro框架** Shiro框架的核心组件包括...
赠送jar包:shiro-cas-1.2.3.jar; 赠送原API文档:shiro-cas-1.2.3-javadoc.jar; 赠送源代码:shiro-cas-1.2.3-sources.jar; 赠送Maven依赖信息文件:shiro-cas-1.2.3.pom; 包含翻译后的API文档:shiro-cas-...
赠送jar包:shiro-config-core-1.4.0.jar; 赠送原API文档:shiro-config-core-1.4.0-javadoc.jar; 赠送源代码:shiro-config-core-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-config-core-1.4.0.pom; ...
赠送jar包:shiro-config-ogdl-1.4.0.jar; 赠送原API文档:shiro-config-ogdl-1.4.0-javadoc.jar; 赠送源代码:shiro-config-ogdl-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-config-ogdl-1.4.0.pom; ...
赠送jar包:shiro-core-1.3.2.jar; 赠送原API文档:shiro-core-1.3.2-javadoc.jar; 赠送源代码:shiro-core-1.3.2-sources.jar; 包含翻译后的API文档:shiro-core-1.3.2-javadoc-API文档-中文(简体)版.zip ...
赠送jar包:shiro-cas-1.2.3.jar; 赠送原API文档:shiro-cas-1.2.3-javadoc.jar; 赠送源代码:shiro-cas-1.2.3-sources.jar; 赠送Maven依赖信息文件:shiro-cas-1.2.3.pom; 包含翻译后的API文档:shiro-cas-...
赠送jar包:shiro-cache-1.4.0.jar; 赠送原API文档:shiro-cache-1.4.0-javadoc.jar; 赠送源代码:shiro-cache-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-cache-1.4.0.pom; 包含翻译后的API文档:shiro-...
shiro shiro-core-1.7.1 jar shiro漏洞
赠送jar包:shiro-cache-1.4.0.jar; 赠送原API文档:shiro-cache-1.4.0-javadoc.jar; 赠送源代码:shiro-cache-1.4.0-sources.jar; 赠送Maven依赖信息文件:shiro-cache-1.4.0.pom; 包含翻译后的API文档:shiro-...
Apache Shiro是一个强大的Java安全框架,它为应用程序提供了身份验证(Authentication)、授权(Authorization)、会话管理(Session Management)和加密(Cryptography)等核心功能。`shiro-1.7.1.zip`是一个包含...