<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安全認證框架,把心得記錄下來。(原創(chuàng)by:西風吹雨)

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

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

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

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

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

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

    同時,也可以設置cacheManagerConfigFile參數(shù)來指定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參數(shù)設置為native時,那么shrio就將用戶的基本認證信息保存到缺省名稱為shiro-activeSessionCache 的Cache中

    org.apache.shiro.web.mgt.DefaultWebSecurityManager 在sessionMode參數(shù)設置為native時,缺省使用的是DefaultWebSessionManager來管理Session,該管理類缺省使用的是使用MemorySessionDAO基于內(nèi)存來保存和操作用戶基本認證信息。

    如果系統(tǒng)內(nèi)的用戶數(shù)特別多,我們需要使用CacheSessionDao來基于Cache進行操作,因此,這里需要顯示配置一個sessionManager(org.apache.shiro.web.session.mgt.DefaultWebSessionManager),并配置該sessionManager的sessionDao為CacheSessionDao(org.apache.shiro.session.mgt.eis.CachingSessionDAO,需用其實現(xiàn)類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,在某些情況下,我們也可以通過實現(xiàn)自定義的sessionDao來把用戶認證信息保存在memcache,mongodb,ldap,database中,達到和其他應用共享用戶認證信息的目的,以此達到SSO的目的(當然,sessionId得一致,這個屬于我們可以在應用商定怎么設定一致的sessionId的問題)。

    b、cacheManager我們也可以自己實現(xiàn)一個,可以根據(jù)應用情況來考慮,比如存放在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/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中,也可以考慮通過一個文本文件,我們讀入內(nèi)容后設置進去。或者通過Ini類來裝入Ini文件內(nèi)容,到時取出urls的部分來設置給shiroFilter的filterChainDefinitions。也可以把這部分數(shù)據(jù)存入數(shù)據(jù)庫表中,到時讀出一個Map來設置給shiroFilter的filterChainDefinitionsMap屬性。

    6、url的配置
    authc是認證用戶(rememberMe的用戶也必須再次登錄才能訪問該url),配置成user才能讓rememberMe用戶也可以訪問。

    7、rememberMe Cookie的處理
    Shiro有一套缺省機制,由CookieRememberMeManager實現(xiàn)。其有一個SimpleCookie類,保存對應的用戶信息等。

    每次保存時,系統(tǒng)把SimpleCookie的信息設置好之后,先用DefaultSerializer把其用jvm缺省序列化方式序列化成byte[],然后再用cipherService(缺省是aes加密算法)來加密該byte[],最后用Base64.encodeToString(serialized)壓縮成一個字符串,再寫入名稱為rememberMe的Cookie中。

    讀取時,通過把該rememberMe Cookie的內(nèi)容用byte[] decoded = Base64.decode(base64)解壓出該byte[],再用cipherService解密,最后用DefaultSerializer反序列化出來該SimpleCookie類。

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

    在Spring配置中,配置好RememberMeManager,裝配上sericerlizer和cipherService(根據(jù)實際情況選用適當?shù)募用芩惴ǎ詈蟀裷ememberMeManager設置給DefaultWebSecurityManager即可。如果非常簡單的cookie,可以直接實現(xiàn)RememberMeManager的幾個接口方法也行。

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


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導航:
     
    主站蜘蛛池模板: 亚洲乱亚洲乱少妇无码| 久草视频在线免费| 亚洲综合色在线观看亚洲| 国产成人精品亚洲| 午夜毛片不卡高清免费| 两个人的视频高清在线观看免费| 亚洲国产精品人久久| 久爱免费观看在线网站| 女人被男人桶得好爽免费视频 | 久久亚洲精品中文字幕无码| a毛片在线还看免费网站| 免费成人激情视频| 在线观看亚洲AV日韩AV| 中国在线观看免费的www| 狠狠色伊人亚洲综合成人| 精品无码国产污污污免费网站| 亚洲视频手机在线| 女性无套免费网站在线看| 美女视频黄a视频全免费网站色| 亚洲国产精品无码久久久久久曰 | 亚洲a一级免费视频| 亚洲国产中文在线视频| 日韩一区二区在线免费观看| 色噜噜综合亚洲av中文无码| 青青久久精品国产免费看| 99久久免费国产精品特黄| 豆国产96在线|亚洲| 久久精品国产亚洲精品| 国产精品亚洲一区二区三区久久 | 亚洲乱码一二三四区国产| 大香人蕉免费视频75| xxxxx做受大片在线观看免费| 好吊妞998视频免费观看在线| 成人在线免费视频| 免费观看国产精品| 久久这里只精品99re免费| 亚洲AV无码乱码麻豆精品国产| 18禁美女裸体免费网站| 久久青青成人亚洲精品| 九九九精品视频免费| 亚洲麻豆精品果冻传媒|