安全认证框架-Apache Shiro研究心得(转)
expirations explicitly.? If we set it to false andthen set corresponding timeToIdle and timeToLive properties,
ehcache would evict sessions without Shiro's knowledge, which wouldcause many problems
(e.g. "My Shiro session timeout is 30 minutes - why isn't a sessionavailable after 2 minutes?"
Answer - ehcache expired it due to the timeToIdle property set to120 seconds.)
diskPersistent=true since we want an enterprise sessionmanagement feature - ability to use sessions after
even after a JVM restart.?-->
???<cache name="shiro-activeSessionCache"
??????????maxElementsInMemory="10000"
??????????eternal="true"
??????????overflowToDisk="true"
??????????diskPersistent="true"
??????????diskExpiryThreadIntervalSeconds="600"/>
???<cache name="shiro.authorizationCache"
??????????maxElementsInMemory="100"
??????????eternal="false"
??????????timeToLiveSeconds="600"
??????????overflowToDisk="false"/>
</ehcache>
?
当我们把securityManager的sessionMode参数设置为native时,那么shrio就将用户的基本认证信息保存到缺省名称为shiro-activeSessionCache的Cache中
org.apache.shiro.web.mgt.DefaultWebSecurityManager在sessionMode参数设置为native时,缺省使用的是DefaultWebSessionManager来管理Session,该管理类缺省使用的是使用MemorySessionDAO基于内存来保存和操作用户基本认证信息。如果系统内的用户数特别多,我们需要使用CacheSessionDao来基于Cache进行操作,因此,这里需要显示配置一个sessionManager(org.apache.shiro.web.session.mgt.DefaultWebSessionManager),并配置该sessionManager的sessionDao为CacheSessionDao(org.apache.shiro.session.mgt.eis.CachingSessionDAO,需用其实现类org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO)。配置CacheSessionDao时,我们可以指定属性activeSessionsCacheName的名称来替换掉缺省名shiro-activeSessionCache。
我们再把该sessionManager配置给DefaultWebSecurityManager就可以了。
?
???<bean id="securityManager"class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
???????<property name="cacheManager"ref="cacheManager"/>
???????<property name="sessionMode"value="native"/>
???????<!-- Single realm app.? If you havemultiple realms, use the 'realms' property instead.-->
???????<property name="realm"ref="myRealm"/>
???????<property name="sessionManager"ref="sessionManager"/>
???</bean>
???<bean id="sessionManager"class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
???????<property name="sessionDAO"ref="sessionDAO"/>
???</bean>
???<bean id="sessionDAO"class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
???????<property name="activeSessionsCacheName"value="shiro-activeSessionCache"/>
???</bean>
?
从以上我们可以看出
??a、我们可以指定sessionManager的sessionDao,在某些情况下,我们也可以通过实现自定义的sessionDao来把用户认证信息保存在memcache,mongodb,ldap,database中,达到和其他应用共享用户认证信息的目的,以此达到SSO的目的(当然,sessionId得一致,这个属于我们可以在应用商定怎么设定一致的sessionId的问题)。
??b、cacheManager我们也可以自己实现一个,可以根据应用情况来考虑,比如存放在memcache中之类。
?
?
4、配置
???Web项目中,普通的web项目可以采用ini文件来对shiro进行配置。基于spring的项目可以采用和Spring集成的方式配置。
?
基于Spring集成的Web项目的基本配置文件如下:
<?xml version="1.0"encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
??????xmlns:context="http://www.springframework.org/schema/context"
??????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
??????xmlns:util="http://www.springframework.org/schema/util"
??????xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd
??????http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsd
??????http://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util-3.0.xsd">
???<!--=========================================================
????????Shiro Core Components - Not Spring Specific
????????=========================================================-->
???<!-- Shiro's main business-tier object forweb-enabled applications
????????(use DefaultSecurityManager instead when there is no webenvironment)-->
???<bean id="securityManager"class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
???????<property name="cacheManager"ref="cacheManager"/>
???????<!-- Single realm app.? If you havemultiple realms, use the 'realms' property instead.-->
???????<property name="sessionMode"value="native"/>
???????<property name="realm"ref="myRealm"/>
???</bean>
???<!-- Let's use some enterprise caching support forbetter performance.? You can replace this with anyenterprise
????????caching framework implementation that you like (Terracotta+Ehcache,Coherence, GigaSpaces, etc -->
???<bean id="cacheManager"class="org.apache.shiro.cache.ehcache.EhCacheManager">
???????<!-- Set a net.sf.ehcache.CacheManager instance hereif you already have one.? If not, a new one
????????????will be creaed with a defaultconfig:???????????????-->
???????<property name="cacheManager"ref="ehCacheManager"/>
???????<!-- If you don't have a pre-builtnet.sf.ehcache.CacheManager instance to inject, but you want
????????????a specific Ehcache configuration to be used, specify thathere.? If you don't, a default
????????????will be used.:
???????<property name="cacheManagerConfigFile"value="classpath:some/path/to/ehcache.xml"/>-->
???</bean>
???<!-- Used by the SecurityManager to access securitydata (users, roles, etc).
????????Many other realm implementations can be used too(PropertiesRealm,
????????LdapRealm, etc. -->
???<bean id="jdbcRealm"class="org.apache.shiro.realm.jdbc.JdbcRealm">
???????<property name="name"value="jdbcRealm"/>
???????<property name="dataSource"ref="dataSource"/>
???????<propertyname="credentialsMatcher">
???????????<!-- The 'bootstrapDataPopulator' Sha256 hashes thepassword
????????????????(using the username as the salt) then base64 encodes it:-->
???????????<beanclass="org.apache.shiro.authc.credential.Sha256CredentialsMatcher">
???????????????<!-- true means hex encoded, false means base64encoded -->
???????????????<property name="storedCredentialsHexEncoded"value="false"/>
???????????????<!-- We salt the password using the username, themost common practice: -->
???????????????<property name="hashSalted"value="true"/>
???????????</bean>
???????</property>
???????<property name="authorizationCacheName"value="shiro.authorizationCache"/>
???</bean>
???<bean id="myRealm"class="org.apache.shiro.realm.text.IniRealm"init-method="init">
???????<property name="name"value="myRealm"/>
???????<property name="authorizationCacheName"value="shiro.authorizationCache"/>
???????<property name="resourcePath"value="classpath:config/myRealm.ini"/>
???</bean>
???<!--=========================================================
????????Shiro Spring-specific integration
????????=========================================================-->
???<!-- Post processor that automatically invokesinit() and destroy() methods
????????for Spring-configured Shiro objects so you don't have to
????????1) specify an init-method and destroy-method attributes for everybean
???????????definition and
????????2) even know which Shiro objects require these methods to be
???????????called. -->
???<bean id="lifecycleBeanPostProcessor"class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
???<!-- Enable Shiro Annotations for Spring-configuredbeans.? Only run after
????????the lifecycleBeanProcessor has run: -->
???<beanclass="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
?????????depends-on="lifecycleBeanPostProcessor"/>
???<beanclass="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
???????<property name="securityManager"ref="securityManager"/>
???</bean>
???<!-- Secure Spring remoting:?Ensure any Spring Remoting method invocations can beassociated
????????with a Subject for security checks. -->
???<bean id="secureRemoteInvocationExecutor"class="org.apache.shiro.spring.remoting.SecureRemoteInvocationExecutor">
???????<property name="securityManager"ref="securityManager"/>
???</bean>
???<!-- Define the Shiro Filter here (as a FactoryBean)instead of directly in web.xml -
????????web.xml uses the DelegatingFilterProxy to access thisbean.? This allows us
????????to wire things with more control as well utilize nice Spring thingssuch as
????????PropertiesPlaceholderConfigurer and abstract beans or anything elsewe might need: -->
???<bean id="shiroFilter"class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
???????<property name="securityManager"ref="securityManager"/>
???????<property name="loginUrl"value="/login"/>
???????<property name="successUrl"value="/index"/>
???????<property name="unauthorizedUrl"value="/unauthorized"/>
???????<!-- The 'filters' property is not necessary sinceany declared javax.servlet.Filter bean
????????????defined will be automatically acquired and available via itsbeanName in chain
????????????definitions, but you can perform overrides or parent/childconsolidated configuration
????????????here if you like: -->
???????<!-- <propertyname="filters">
???????????<util:map>
???????????????<entry key="aName"value-ref="someFilterPojo"/>
???????????</util:map>
???????</property> -->
???????<propertyname="filterChainDefinitions">
???????????<value>
???????????????/login = authc
???????????????/account = user
???????????????/manage = user,roles[admin]
???????????</value>
???????</property>
???</bean>
</beans>
5、基于url资源的权限管理
????我们可以简单配置在shiroFilter的filterChainDefinitions中,也可以考虑通过一个文本文件,我们读入内容后设置进去。或者通过Ini类来装入Ini文件内容,到时取出urls的部分来设置给shiroFilter的filterChainDefinitions。也可以把这部分数据存入数据库表中,到时读出一个Map来设置给shiroFilter的filterChainDefinitionsMap属性。
?
6、url的配置
??authc是认证用户(rememberMe的用户也必须再次登录才能访问该url),配置成user才能让rememberMe用户也可以访问。
?
7、rememberMe Cookie的处理
???Shiro有一套缺省机制,由CookieRememberMeManager实现。
其有一个SimpleCookie类,保存对应的用户信息等。每次保存时,系统把SimpleCookie的信息设置好之后,先用DefaultSerializer把其用jvm缺省序列化方式序列化成byte[],然后再用cipherService(缺省是aes加密算法)来加密该byte[],最后用Base64.encodeToString(serialized)压缩成一个字符串,再写入名称为rememberMe的Cookie中。
?
读取时,通过把该rememberMe Cookie的内容用byte[] decoded =Base64.decode(base64)解压出该byte[],再用cipherService解密,最后用DefaultSerializer反序列化出来该SimpleCookie类。
?
如果我们有自定义的rememberMeCookie需要处理,特别是在和其他网站一起SSO,通过访问主域的Cookie来获取记录的用户信息时,我们需要重新实现rememberMeManager(可以考虑继承AbstractRememberMeManager),和根据实际用的序列化方式Serializer来实现一个(比如考虑通用性,用json方式序列化)。在Spring配置中,配置好RememberMeManager,装配上sericerlizer和cipherService(根据实际情况选用适当的加密算法),最后把rememberMeManager设置给DefaultWebSecurityManager即可。如果非常简单的cookie,可以直接实现RememberMeManager的几个接口方法也行。
?
说到这里, ApacheShiro的一些基本配置和扩展情况应该差不多了。关于它的授权和使用等模型,其官网有基本的说明,也有相关的例子。这里主要是针对其实际应用中的一些使用和扩展方式。
?
?
原文链接:http://blog.sina.com.cn/s/blog_6638b10d0100pd88.html