<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    paulwong

    安全認證框架-Apache Shiro研究心得

    最近因為項目需要,研究了一下Apache Shiro安全認證框架,把心得記錄下來。(原創by:西風吹雨)

    Apache Shrio是一個安全認證框架,和Spring Security相比,在于他使用了和比較簡潔易懂的認證和授權方式。其提供的native-session(即把用戶認證后的授權信息保存在其自身提供Session中)機制,這樣就可以和HttpSession、EJB Session Bean的基于容器的Session脫耦,到到和客戶端應用、Flex應用、遠程方法調用等都可以使用它來配置權限認證。

    1、sessionMode
    在普通的WEB項目中,我們可以選擇使用native session或者是HttpSession,通過設置securityManager的sessionMode參數為http或native即可。

    2、realm
    我們可以基于jdbc,ldap,text,activeDirectory,jndi等多種方式來獲取用戶基本信息,角色信息,權限信息等。只需要在securityManager中指定使用相應的realm實現即可,其在這各方面都提供了對應的缺省實現,比如我們常用的基于數據庫表的形式來配置用戶權限信息,就可以使用其缺省實現的jdbcRealm(org.apache.shiro.realm.jdbc.JdbcRealm)。

    當然,如果認證信息來自于多方面,多個不同的來源(比如來自兩個庫中,或者一個數據庫,一個是ldap,再配上一個缺省的基于文本的測試用等等),我們可以為securityManager指定realms參數,即把這一組安全配置都配置上。各個具體的realm實現提供了方法來獲取用戶基本信息、角色、權限等。 realm的授權信息可以存放在Cache中,Cache的名稱可以通過設置其authorizationCacheName參數指定。

    3、緩存
    目前Shrio缺省提供了基于ehCache來緩存用戶認證信息和授權信息的實現。只需要配置 org.apache.shiro.web.mgt.DefaultWebSecurityManager 這個 cacheManager并設置給SecurityManager即可。

    如果項目中已經存在使用的ehCacheManager配置(org.springframework.cache.ehcache.EhCacheManagerFactoryBean),DefaultWebSecurityManager則可以指定使用現有的ehCacheManager,如果不指定,它將自行使用缺省配置創建一個。

    同時,也可以設置cacheManagerConfigFile參數來指定ehCache的配置文件。 下例中的shiro.authorizationCache是用來存放授權信息的Cache,我們在配置realm(如myRealm或jdbcReaml)時,把authorizationCacheName屬性設置shiro.authorizationCache來對應。

    ehcache.xml  
    <ehcache>

    <diskStore path="java.io.tmpdir/tuan-oauth"/>



    <defaultCache
    maxElementsInMemory="10000"
    eternal
    ="false"
    timeToIdleSeconds
    ="120"
    timeToLiveSeconds
    ="120"
    overflowToDisk
    ="false"
    diskPersistent
    ="false"
    diskExpiryThreadIntervalSeconds
    ="120"
    />

    <!-- We want eternal="true" (with no timeToIdle or timeToLive settings) because Shiro manages session
    expirations explicitly. If we set it to false and then set corresponding timeToIdle and timeToLive properties,
    ehcache would evict sessions without Shiro's knowledge, which would cause many problems
    (e.g. "My Shiro session timeout is 30 minutes - why isn't a session available after 2 minutes?"
    Answer - ehcache expired it due to the timeToIdle property set to 120 seconds.)

    diskPersistent=true since we want an enterprise session management 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 have multiple 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進行配置?;趕pring的項目可以采用和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/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"
    >

        
    <!-- ========================================================= Shiro Core 
            Components - Not Spring Specific ========================================================= 
    -->

        
    <!-- Shiro's main business-tier object for web-enabled applications (use 
            DefaultSecurityManager instead when there is no web environment) 
    -->
        
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            
    <property name="cacheManager" ref="cacheManager" />
            
    <!-- Single realm app. If you have multiple realms, use the 'realms' property 
                instead. 
    -->
            
    <property name="sessionMode" value="native" />
            
    <property name="realm" ref="myRealm" />
        
    </bean>

        
    <!-- Let's use some enterprise caching support for better performance. You 
            can replace this with any enterprise 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 here if you already have 
                one. If not, a new one will be creaed with a default config: 
    -->
            
    <property name="cacheManager" ref="ehCacheManager" />
            
    <!-- If you don't have a pre-built net.sf.ehcache.CacheManager instance 
                to inject, but you want a specific Ehcache configuration to be used, specify 
                that here. 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 security data (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" />
            
    <property name="credentialsMatcher">
                
    <!-- The 'bootstrapDataPopulator' Sha256 hashes the password (using the 
                    username as the salt) then base64 encodes it: 
    -->
                
    <bean class="org.apache.shiro.authc.credential.Sha256CredentialsMatcher">
                    
    <!-- true means hex encoded, false means base64 encoded -->
                    
    <property name="storedCredentialsHexEncoded" value="false" />
                    
    <!-- We salt the password using the username, the most 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 invokes init() and destroy() methods 
            for Spring-configured Shiro objects so you don't have to 1) specify an init-method 
            and destroy-method attributes for every bean 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-configured beans. Only run after 
            the lifecycleBeanProcessor has run: 
    -->
        
    <bean
            
    class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
            depends-on
    ="lifecycleBeanPostProcessor" />
        
    <bean
            
    class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
            
    <property name="securityManager" ref="securityManager" />
        
    </bean>


        
    <!-- Secure Spring remoting: Ensure any Spring Remoting method invocations 
            can be associated 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 this bean. 
            This allows us to wire things with more control as well utilize nice Spring 
            things such as PropertiesPlaceholderConfigurer and abstract beans or anything 
            else we 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 since any declared javax.servlet.Filter 
                bean defined will be automatically acquired and available via its beanName 
                in chain definitions, but you can perform overrides or parent/child consolidated 
                configuration here if you like: 
    -->
            
    <!-- <property name="filters"> <util:map> <entry key="aName" value-ref="someFilterPojo"/> 
                </util:map> </property> 
    -->
            
    <property name="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類。

    如果我們有自定義的rememberMe Cookie需要處理,特別是在和其他網站一起SSO,通過訪問主域的Cookie來獲取記錄的用戶信息時,我們需要重新實現rememberMeManager(可以考慮繼承AbstractRememberMeManager),和根據實際用的序列化方式Serializer來實現一個(比如考慮通用性,用json方式序列化)。

    在Spring配置中,配置好RememberMeManager,裝配上sericerlizer和cipherService(根據實際情況選用適當的加密算法),最后把rememberMeManager設置給DefaultWebSecurityManager即可。如果非常簡單的cookie,可以直接實現RememberMeManager的幾個接口方法也行。

    posted on 2012-01-28 16:07 paulwong 閱讀(18944) 評論(0)  編輯  收藏 所屬分類: Apache Shiro

    主站蜘蛛池模板: 最新中文字幕免费视频| 无码一区二区三区亚洲人妻| 亚洲av再在线观看| 波多野结衣在线免费视频| 91精品成人免费国产| 精品国产亚洲AV麻豆 | 亚洲s码欧洲m码吹潮| 久久久久久亚洲精品| 亚洲XX00视频| 国产精品免费播放| 免费无码A片一区二三区| 麻豆成人久久精品二区三区免费| 国产精品小视频免费无限app| 精品久久久久久久久亚洲偷窥女厕| 亚洲国产精品成人综合色在线婷婷| 亚洲精品乱码久久久久久| 亚洲精品天堂成人片?V在线播放| 精品国产麻豆免费网站| 猫咪社区免费资源在线观看| 免费看男女下面日出水来| 久久精品一本到99热免费| 国产成人AV片无码免费| 在线免费观看伊人三级电影| 一级成人a免费视频| 免费人成网站永久| 天堂亚洲免费视频| 全部在线播放免费毛片| 农村寡妇一级毛片免费看视频| 直接进入免费看黄的网站| 美国免费高清一级毛片| 狠狠热精品免费观看| 九九全国免费视频| 日韩精品视频在线观看免费| 日产久久强奸免费的看| 国产精品免费看久久久香蕉| 男女一边摸一边做爽的免费视频 | 久久伊人亚洲AV无码网站| 亚洲欧洲精品成人久久奇米网 | 亚洲情A成黄在线观看动漫软件| 亚洲一级免费视频| 亚洲色大网站WWW永久网站|