分佈式集羣系統下的高可用session解決方案—Session共享

Apache shiro集羣實現 (一) shiro入門介紹

Apache shiro集羣實現 (二) shiro 的INI配置

Apache shiro集羣實現 (三)shiro身份認證(Shiro Authentication)

Apache shiro集羣實現 (四)shiro授權(Authentication)–訪問控制

Apache shiro集羣實現 (五)分佈式集羣系統下的高可用session解決方案

Apache shiro集羣實現 (六)分佈式集羣系統下的高可用session解決方案—Session共享



      Apache Shiro的基本配置和構成這裏就不詳細說明了,其官網有說明文檔,這裏僅僅說明集羣的解決方案,詳細配置:shiro web config

    Apache Shiro集羣要解決2個問題,一個是session的共享問題,一個是授權信息的cache共享問題,官網給的例子是Ehcache的實現,在配置說明上不算很詳細,我這裏用nosql(Redis)替代了ehcache做了session和cache的存儲。


shiro spring的默認配置(單機,非集羣)


  1. <span style=“font-size:18px;”><span style=“font-size:18px;”><bean id=“securityManager” class=“org.apache.shiro.web.mgt.DefaultWebSecurityManager”>    
  2.     <property name=“realm” ref=“shiroDbRealm” />    
  3.     <property name=“cacheManager” ref=“memoryConstrainedCacheManager” />    
  4. </bean>    
  5.     
  6. <!– 自定義Realm –>    
  7. <bean id=“shiroDbRealm” class=“com.xxx.security.shiro.custom.ShiroDbRealm”>    
  8.     <property name=“credentialsMatcher” ref=“customCredentialsMather”></property>    
  9. </bean>     
  10. <!– 用戶授權信息Cache(本機內存實現) –>    
  11. <bean id=“memoryConstrainedCacheManager” class=“org.apache.shiro.cache.MemoryConstrainedCacheManager” />      
  12.     
  13. <!– 保證實現了Shiro內部lifecycle函數的bean執行 –>    
  14. <bean id=“lifecycleBeanPostProcessor” class=“org.apache.shiro.spring.LifecycleBeanPostProcessor”/>    
  15.     
  16. <bean id=“shiroFilter” class=“org.apache.shiro.spring.web.ShiroFilterFactoryBean”>    
  17.     <property name=“securityManager” ref=“securityManager” />    
  18.     <property name=“loginUrl” value=“/login” />    
  19.     <property name=“successUrl” value=“/project” />    
  20.     <property name=“filterChainDefinitions”>    
  21.         <value>    
  22.         /login = authc    
  23.         /logout = logout                
  24.     </value>    
  25.     </property>    
  26. </bean> </span></span>  
<span style="font-size:18px;"><span style="font-size:18px;"><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
    <property name="realm" ref="shiroDbRealm" />  
    <property name="cacheManager" ref="memoryConstrainedCacheManager" />  
</bean>  

<!-- 自定義Realm -->  
<bean id="shiroDbRealm" class="com.xxx.security.shiro.custom.ShiroDbRealm">  
    <property name="credentialsMatcher" ref="customCredentialsMather"></property>  
</bean>   
<!-- 用戶授權信息Cache(本機內存實現) -->  
<bean id="memoryConstrainedCacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager" />    

<!-- 保證實現了Shiro內部lifecycle函數的bean執行 -->  
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>  

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
    <property name="securityManager" ref="securityManager" />  
    <property name="loginUrl" value="/login" />  
    <property name="successUrl" value="/project" />  
    <property name="filterChainDefinitions">  
        <value>  
        /login = authc  
        /logout = logout              
    </value>  
    </property>  
</bean> </span></span>

上面的配置是shiro非集羣下的配置,DefaultWebSecurityManager類不需要注入sessionManager屬性,它會使用默認的sessionManager類,請看源碼


  1. <span style=“font-size:18px;”><span style=“font-size:18px;”>    public DefaultWebSecurityManager() {    
  2.             super();    
  3.             ((DefaultSubjectDAO) this.subjectDAO).setSessionStorageEvaluator(new DefaultWebSessionStorageEvaluator());    
  4.             this.sessionMode = HTTP_SESSION_MODE;    
  5.             setSubjectFactory(new DefaultWebSubjectFactory());    
  6.             setRememberMeManager(new CookieRememberMeManager());    
  7.             setSessionManager(new ServletContainerSessionManager());    
  8.     }  </span></span>  
<span style="font-size:18px;"><span style="font-size:18px;">    public DefaultWebSecurityManager() {  
            super();  
            ((DefaultSubjectDAO) this.subjectDAO).setSessionStorageEvaluator(new DefaultWebSessionStorageEvaluator());  
            this.sessionMode = HTTP_SESSION_MODE;  
            setSubjectFactory(new DefaultWebSubjectFactory());  
            setRememberMeManager(new CookieRememberMeManager());  
            setSessionManager(new ServletContainerSessionManager());  
    }  </span></span>

在最後一行,set了默認的servlet容器實現的sessionManager,sessionManager會管理session的創建、刪除等等。如果我們需要讓session在集羣中共享,就需要替換這個默認的sessionManager。在其官網上原話是這樣的:


  1. <span style=“font-size:18px;”><span style=“font-size:18px;”>    Native Sessions    
  2.         
  3.     If you want your session configuration settings and clustering to be portable across servlet containers    
  4.     (e.g. Jetty in testing, but Tomcat or JBoss in production), or you want to control specific session/clustering     
  5.     features, you can enable Shiro’s native session management.    
  6.         
  7.     The word ‘Native’ here means that Shiro’s own enterprise session management implementation will be used to support     
  8.     all Subject and HttpServletRequest sessions and bypass the servlet container completely. But rest assured - Shiro     
  9.     implements the relevant parts of the Servlet specification directly so any existing web/http related code works as     
  10.     expected and never needs to ‘know’ that Shiro is transparently managing sessions.    
  11.         
  12.     DefaultWebSessionManager    
  13.         
  14.     To enable native session management for your web application, you will need to configure a native web-capable     
  15.     session manager to override the default servlet container-based one. You can do that by configuring an instance of     
  16.     DefaultWebSessionManager on Shiro’s SecurityManager.   </span></span>  
<span style="font-size:18px;"><span style="font-size:18px;">    Native Sessions  

    If you want your session configuration settings and clustering to be portable across servlet containers  
    (e.g. Jetty in testing, but Tomcat or JBoss in production), or you want to control specific session/clustering   
    features, you can enable Shiro's native session management.  

    The word 'Native' here means that Shiro's own enterprise session management implementation will be used to support   
    all Subject and HttpServletRequest sessions and bypass the servlet container completely. But rest assured - Shiro   
    implements the relevant parts of the Servlet specification directly so any existing web/http related code works as   
    expected and never needs to 'know' that Shiro is transparently managing sessions.  

    DefaultWebSessionManager  

    To enable native session management for your web application, you will need to configure a native web-capable   
    session manager to override the default servlet container-based one. You can do that by configuring an instance of   
    DefaultWebSessionManager on Shiro's SecurityManager.   </span></span>

我們可以看到如果要用集羣,就需要用本地會話,這裏shiro給我準備了一個默認的native session manager,DefaultWebSessionManager,所以我們要修改spring配置文件,注入DefaultWebSessionManager


  1. <span style=”font-size:18px;”><span style=”font-size:18px;”>    <bean id=”securityManager” class=”org.apache.shiro.web.mgt.DefaultWebSecurityManager”>    
  2.         <property name=”sessionManager” ref=”defaultWebSessionManager” />    
  3.         <property name=”realm” ref=”shiroDbRealm” />    
  4.         <property name=”cacheManager” ref=”memoryConstrainedCacheManager” />    
  5.     </bean>    
  6.     <bean id=”defaultWebSessionManager” class=”org.apache.shiro.web.session.mgt.DefaultWebSessionManager”>    
  7.         <property name=”globalSessionTimeout” value=”1200000” />    
  8.     </bean>  </span></span>  
<span style="font-size:18px;"><span style="font-size:18px;">    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
        <property name="sessionManager" ref="defaultWebSessionManager" />  
        <property name="realm" ref="shiroDbRealm" />  
        <property name="cacheManager" ref="memoryConstrainedCacheManager" />  
    </bean>  
    <bean id="defaultWebSessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">  
        <property name="globalSessionTimeout" value="1200000" />  
    </bean>  </span></span>
我們繼續看DefaultWebSessionManager的源碼,發現其父類DefaultSessionManager中有sessionDAO屬性,這個屬性是真正實現了session儲存的類,這個就是我們自己實現的redis session的儲存類。


  1. <span style=“font-size:18px;”><span style=“font-size:18px;”>    protected SessionDAO sessionDAO;    
  2.         
  3.     private CacheManager cacheManager;    
  4.         
  5.     private boolean deleteInvalidSessions;    
  6.         
  7.     public DefaultSessionManager() {    
  8.         this.deleteInvalidSessions = true;    
  9.         this.sessionFactory = new SimpleSessionFactory();    
  10.         this.sessionDAO = new MemorySessionDAO();    
  11.     }  </span></span>  
<span style="font-size:18px;"><span style="font-size:18px;">    protected SessionDAO sessionDAO;  

    private CacheManager cacheManager;  

    private boolean deleteInvalidSessions;  

    public DefaultSessionManager() {  
        this.deleteInvalidSessions = true;  
        this.sessionFactory = new SimpleSessionFactory();  
        this.sessionDAO = new MemorySessionDAO();  
    }  </span></span>

這裏我們看到了,如果不自己注入sessionDAO,defaultWebSessionManager會使用MemorySessionDAO做爲默認實現類,這個肯定不是我們想要的,所以這就自己動手實現sessionDAO吧。


  1. <span style=“font-size:18px;”><span style=“font-size:18px;”>package com.tgb.itoo.authority.cache;  
  2.   
  3. import java.io.Serializable;  
  4. import java.util.Collection;  
  5. import java.util.HashSet;  
  6. import java.util.Set;  
  7.   
  8. import org.apache.shiro.session.Session;  
  9. import org.apache.shiro.session.UnknownSessionException;  
  10. import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;  
  11. import org.slf4j.Logger;  
  12. import org.slf4j.LoggerFactory;  
  13.   
  14. public class RedisSessionDAO extends AbstractSessionDAO {  
  15.   
  16.     private static Logger logger = LoggerFactory.getLogger(RedisSessionDAO.class);  
  17.     /** 
  18.      * shiro-redis的session對象前綴 
  19.      */  
  20.     private RedisManager redisManager;  
  21.       
  22.     /** 
  23.      * The Redis key prefix for the sessions  
  24.      */  
  25.     private String keyPrefix = “shiro_redis_session:”;  
  26.       
  27.     @Override  
  28.     public void update(Session session) throws UnknownSessionException {  
  29.         this.saveSession(session);  
  30.     }  
  31.       
  32.     /** 
  33.      * save session 
  34.      * @param session 
  35.      * @throws UnknownSessionException 
  36.      */  
  37.     private void saveSession(Session session) throws UnknownSessionException{  
  38.         if(session == null || session.getId() == null){  
  39.             logger.error(”session or session id is null”);  
  40.             return;  
  41.         }  
  42.           
  43.         byte[] key = getByteKey(session.getId());  
  44.         byte[] value = SerializeUtils.serialize(session);  
  45.         session.setTimeout(redisManager.getExpire()*1000);        
  46.         this.redisManager.set(key, value, redisManager.getExpire());  
  47.     }  
  48.   
  49.     @Override  
  50.     public void delete(Session session) {  
  51.         if(session == null || session.getId() == null){  
  52.             logger.error(”session or session id is null”);  
  53.             return;  
  54.         }  
  55.         redisManager.del(this.getByteKey(session.getId()));  
  56.   
  57.     }  
  58.   
  59.     //用來統計當前活動的session  
  60.     @Override  
  61.     public Collection<Session> getActiveSessions() {  
  62.         Set<Session> sessions = new HashSet<Session>();  
  63.           
  64.         Set<byte[]> keys = redisManager.keys(this.keyPrefix + “*”);  
  65.         if(keys != null && keys.size()>0){  
  66.             for(byte[] key:keys){  
  67.                 Session s = (Session)SerializeUtils.deserialize(redisManager.get(key));  
  68.                 sessions.add(s);  
  69.             }  
  70.         }  
  71.           
  72.         return sessions;  
  73.     }  
  74.   
  75.     @Override  
  76.     protected Serializable doCreate(Session session) {  
  77.         Serializable sessionId = this.generateSessionId(session);    
  78.         this.assignSessionId(session, sessionId);  
  79.         this.saveSession(session);  
  80.         return sessionId;  
  81.     }  
  82.   
  83.     @Override  
  84.     protected Session doReadSession(Serializable sessionId) {  
  85.         if(sessionId == null){  
  86.             logger.error(”session id is null”);  
  87.             return null;  
  88.         }  
  89.           
  90.         Session s = (Session)SerializeUtils.deserialize(redisManager.get(this.getByteKey(sessionId)));  
  91.         return s;  
  92.     }  
  93.       
  94.     /** 
  95.      * 獲得byte[]型的key 
  96.      * @param key 
  97.      * @return 
  98.      */  
  99.     private byte[] getByteKey(Serializable sessionId){  
  100.         String preKey = this.keyPrefix + sessionId;  
  101.         return preKey.getBytes();  
  102.     }  
  103.   
  104.     public RedisManager getRedisManager() {  
  105.         return redisManager;  
  106.     }  
  107.   
  108.     public void setRedisManager(RedisManager redisManager) {  
  109.         this.redisManager = redisManager;  
  110.           
  111.         /** 
  112.          * 初始化redisManager 
  113.          */  
  114.         this.redisManager.init();  
  115.     }  
  116.   
  117.     /** 
  118.      * Returns the Redis session keys 
  119.      * prefix. 
  120.      * @return The prefix 
  121.      */  
  122.     public String getKeyPrefix() {  
  123.         return keyPrefix;  
  124.     }  
  125.   
  126.     /** 
  127.      * Sets the Redis sessions key  
  128.      * prefix. 
  129.      * @param keyPrefix The prefix 
  130.      */  
  131.     public void setKeyPrefix(String keyPrefix) {  
  132.         this.keyPrefix = keyPrefix;  
  133.     }  
  134. }  
  135. </span></span>  
<span style="font-size:18px;"><span style="font-size:18px;">package com.tgb.itoo.authority.cache;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RedisSessionDAO extends AbstractSessionDAO {

    private static Logger logger = LoggerFactory.getLogger(RedisSessionDAO.class);
    /**
     * shiro-redis的session對象前綴
     */
    private RedisManager redisManager;

    /**
     * The Redis key prefix for the sessions 
     */
    private String keyPrefix = "shiro_redis_session:";

    @Override
    public void update(Session session) throws UnknownSessionException {
        this.saveSession(session);
    }

    /**
     * save session
     * @param session
     * @throws UnknownSessionException
     */
    private void saveSession(Session session) throws UnknownSessionException{
        if(session == null || session.getId() == null){
            logger.error("session or session id is null");
            return;
        }

        byte[] key = getByteKey(session.getId());
        byte[] value = SerializeUtils.serialize(session);
        session.setTimeout(redisManager.getExpire()*1000);      
        this.redisManager.set(key, value, redisManager.getExpire());
    }

    @Override
    public void delete(Session session) {
        if(session == null || session.getId() == null){
            logger.error("session or session id is null");
            return;
        }
        redisManager.del(this.getByteKey(session.getId()));

    }

    //用來統計當前活動的session
    @Override
    public Collection<Session> getActiveSessions() {
        Set<Session> sessions = new HashSet<Session>();

        Set<byte[]> keys = redisManager.keys(this.keyPrefix + "*");
        if(keys != null && keys.size()>0){
            for(byte[] key:keys){
                Session s = (Session)SerializeUtils.deserialize(redisManager.get(key));
                sessions.add(s);
            }
        }

        return sessions;
    }

    @Override
    protected Serializable doCreate(Session session) {
        Serializable sessionId = this.generateSessionId(session);  
        this.assignSessionId(session, sessionId);
        this.saveSession(session);
        return sessionId;
    }

    @Override
    protected Session doReadSession(Serializable sessionId) {
        if(sessionId == null){
            logger.error("session id is null");
            return null;
        }

        Session s = (Session)SerializeUtils.deserialize(redisManager.get(this.getByteKey(sessionId)));
        return s;
    }

    /**
     * 獲得byte[]型的key
     * @param key
     * @return
     */
    private byte[] getByteKey(Serializable sessionId){
        String preKey = this.keyPrefix + sessionId;
        return preKey.getBytes();
    }

    public RedisManager getRedisManager() {
        return redisManager;
    }

    public void setRedisManager(RedisManager redisManager) {
        this.redisManager = redisManager;

        /**
         * 初始化redisManager
         */
        this.redisManager.init();
    }

    /**
     * Returns the Redis session keys
     * prefix.
     * @return The prefix
     */
    public String getKeyPrefix() {
        return keyPrefix;
    }

    /**
     * Sets the Redis sessions key 
     * prefix.
     * @param keyPrefix The prefix
     */
    public void setKeyPrefix(String keyPrefix) {
        this.keyPrefix = keyPrefix;
    }
}
</span></span>


我們自定義RedisSessionDAO繼承AbstractSessionDAO,實現對session操作的方法,可以用redis、mongoDB等進行實現。


這個是自己redis的RedisCacheManager存儲實現類:


  1. <span style=“font-size:18px;”><span style=“font-size:18px;”>package com.tgb.itoo.authority.cache;  
  2.   
  3. import java.util.concurrent.ConcurrentHashMap;  
  4. import java.util.concurrent.ConcurrentMap;  
  5.   
  6. import org.apache.shiro.cache.Cache;  
  7. import org.apache.shiro.cache.CacheException;  
  8. import org.apache.shiro.cache.CacheManager;  
  9. import org.slf4j.Logger;  
  10. import org.slf4j.LoggerFactory;  
  11.   
  12. public class RedisCacheManager implements CacheManager{  
  13.   
  14.     private static final Logger logger = LoggerFactory  
  15.             .getLogger(RedisCacheManager.class);  
  16.   
  17.     // fast lookup by name map  
  18.     private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();  
  19.   
  20.     private RedisManager redisManager;  
  21.   
  22.     /** 
  23.      * The Redis key prefix for caches  
  24.      */  
  25.     private String keyPrefix = “shiro_redis_cache:”;  
  26.       
  27.     /** 
  28.      * Returns the Redis session keys 
  29.      * prefix. 
  30.      * @return The prefix 
  31.      */  
  32.     public String getKeyPrefix() {  
  33.         return keyPrefix;  
  34.     }  
  35.   
  36.     /** 
  37.      * Sets the Redis sessions key  
  38.      * prefix. 
  39.      * @param keyPrefix The prefix 
  40.      */  
  41.     public void setKeyPrefix(String keyPrefix) {  
  42.         this.keyPrefix = keyPrefix;  
  43.     }  
  44.       
  45.     @Override  
  46.     public <K, V> Cache<K, V> getCache(String name) throws CacheException {  
  47.         logger.debug(”獲取名稱爲: ” + name + “ 的RedisCache實例”);  
  48.           
  49.         Cache c = caches.get(name);  
  50.           
  51.         if (c == null) {  
  52.   
  53.             // initialize the Redis manager instance  
  54.             redisManager.init();  
  55.               
  56.             // create a new cache instance  
  57.             c = new RedisCache<K, V>(redisManager, keyPrefix);  
  58.               
  59.             // add it to the cache collection  
  60.             caches.put(name, c);  
  61.         }  
  62.         return c;  
  63.     }  
  64.   
  65.     public RedisManager getRedisManager() {  
  66.         return redisManager;  
  67.     }  
  68.   
  69.     public void setRedisManager(RedisManager redisManager) {  
  70.         this.redisManager = redisManager;  
  71.     }  
  72. }  
  73. </span></span>  
<span style="font-size:18px;"><span style="font-size:18px;">package com.tgb.itoo.authority.cache;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RedisCacheManager implements CacheManager{

    private static final Logger logger = LoggerFactory
            .getLogger(RedisCacheManager.class);

    // fast lookup by name map
    private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();

    private RedisManager redisManager;

    /**
     * The Redis key prefix for caches 
     */
    private String keyPrefix = "shiro_redis_cache:";

    /**
     * Returns the Redis session keys
     * prefix.
     * @return The prefix
     */
    public String getKeyPrefix() {
        return keyPrefix;
    }

    /**
     * Sets the Redis sessions key 
     * prefix.
     * @param keyPrefix The prefix
     */
    public void setKeyPrefix(String keyPrefix) {
        this.keyPrefix = keyPrefix;
    }

    @Override
    public <K, V> Cache<K, V> getCache(String name) throws CacheException {
        logger.debug("獲取名稱爲: " + name + " 的RedisCache實例");

        Cache c = caches.get(name);

        if (c == null) {

            // initialize the Redis manager instance
            redisManager.init();

            // create a new cache instance
            c = new RedisCache<K, V>(redisManager, keyPrefix);

            // add it to the cache collection
            caches.put(name, c);
        }
        return c;
    }

    public RedisManager getRedisManager() {
        return redisManager;
    }

    public void setRedisManager(RedisManager redisManager) {
        this.redisManager = redisManager;
    }
}
</span></span>


這樣RedisSessionDAO我們就完成了,下面繼續修改我們spring配置文件:


  1. <span style=“font-size:18px;”><?xml version=“1.0” encoding=“UTF-8”?>  
  2. <beans xmlns=“http://www.springframework.org/schema/beans”  
  3.     xmlns:aop=“http://www.springframework.org/schema/aop” xmlns:tx=“http://www.springframework.org/schema/tx”  
  4.     xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance” xmlns:jee=“http://www.springframework.org/schema/jee”  
  5.     xmlns:context=“http://www.springframework.org/schema/context”  
  6.     xsi:schemaLocation=”http://www.springframework.org/schema/beans   
  7.     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
  8.     http://www.springframework.org/schema/aop   
  9.     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd   
  10.     http://www.springframework.org/schema/tx    
  11.     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd   
  12.     http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd  
  13.     http://www.springframework.org/schema/context  
  14.     http://www.springframework.org/schema/context/spring-context-3.0.xsd”  
  15.     default-lazy-init=“true”>  
  16.   
  17.     <!– 註解支持 –>  
  18.     <context:annotation-config />  
  19.     <bean id=“propertyConfigurer”  
  20.         class=“org.springframework.beans.factory.config.PropertyPlaceholderConfigurer”>  
  21.         <property name=“locations”>  
  22.             <list>  
  23.                 <value>classpath:config/shiro-cas.properties</value>  
  24.             </list>  
  25.         </property>  
  26.     </bean>  
  27.       
  28.       
  29.       
  30.     <jee:local-slsb id=“PermissionManager”  
  31.         jndi-name=“java:global/itoo-authority-role-ear/itoo-authority-shiro-core-0.0.1-SNAPSHOT/PermissionManager!com.tgb.itoo.authority.service.ShiroBean”  
  32.         business-interface=“com.tgb.itoo.authority.service.ShiroBean”></jee:local-slsb>  
  33.   
  34. <!–     <jee:jndi-lookup id=”PermissionManager” –>  
  35.   
  36. <!–     jndi-name=”ejb:itoo-authority-shiro-ear/itoo-authority-shiro-core-0.0.1-SNAPSHOT/PermissionManager!com.tgb.itoo.authority.service.ShiroBean” –>  
  37.   
  38. <!–     lookup-on-startup=”true” cache=”true” environment-ref=”evn”> –>  
  39.   
  40. <!–     </jee:jndi-lookup> –>  
  41.     <!– shiro過濾器 start –>  
  42.     <bean id=“shiroSecurityFilter” class=“org.apache.shiro.spring.web.ShiroFilterFactoryBean”>  
  43.         <property name=“securityManager” ref=“securityManager”></property>  
  44.         <property name=“loginUrl” value={loginUrl}"</span><span class="tag">&gt;</span><span class="tag">&lt;/</span><span class="tag-name">property</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"successUrl"</span><span>&nbsp;</span><span class="attribute">value</span><span>=</span><span class="attribute-value">" {successUrl}”></property>  
  45.         <property name=“filters”>  
  46.             <map>  
  47.                 <entry key=“casFilter”>  
  48.                     <bean class=“org.apache.shiro.cas.CasFilter”>  
  49.                         <!–配置驗證錯誤時的失敗頁面 /main 爲系統登錄頁面 –>  
  50.                         <property name=“failureUrl” value=“/message.jsp” />  
  51.                     </bean>  
  52.                 </entry>  
  53.             </map>  
  54.         </property>  
  55.         <!– 過濾器鏈,請求url對應的過濾器 –>  
  56.         <property name=“filterChainDefinitions”>  
  57.             <value>  
  58.                 /message.jsp=anon  
  59.                 /logout=logout  
  60.                 /shiro-cas=casFilter  
  61.                 /** =user  
  62.             </value>  
  63.         </property>  
  64.     </bean>  
  65.     <!– shiro過濾器 end –>  
  66.   
  67.     <!– 保證實現shiro內部的生命週期函數bean的執行 –>  
  68.     <bean id=“lifecycleBeanPostProcessor” class=“org.apache.shiro.spring.LifecycleBeanPostProcessor” />  
  69.   
  70.     <!– 第三:shiro管理中心類 start-李社河 –>  
  71.     <bean id=“securityManager” class=“org.apache.shiro.web.mgt.DefaultWebSecurityManager”>  
  72.         <property name=“realm” ref=“shiroRealm”></property>  
  73.         <property name=“sessionMode” value=“http”></property>  
  74.         <property name=“subjectFactory” ref=“casSubjectFactory”></property>  
  75.         <!– ehcahe緩存shiro自帶 –>  
  76.         <!– <property name=”cacheManager” ref=”shiroEhcacheManager”></property> –>  
  77.   
  78.         <!– redis緩存 –>  
  79.         <property name=“cacheManager” ref=“redisCacheManager” />  
  80.   
  81.         <!– sessionManager –>  
  82.         <property name=“sessionManager” ref=“sessionManager”></property>  
  83.     </bean>  
  84.   
  85.   
  86.     <!– 緩存管理器redis-start-李社河-2015年4月14日 –>  
  87.   
  88.     <!– sessionManager –>  
  89.     <!– <bean id=”sessionManager” –>  
  90.     <!– class=”org.apache.shiro.web.session.mgt.DefaultWebSessionManager”> –>  
  91.     <!– <property name=”sessionDAO” ref=”redisSessionDAO” /> –>  
  92.     <!– </bean> –>  
  93.   
  94.     <!– 自定義redisManager-redis –>  
  95.     <bean id=“redisCacheManager” class=“com.tgb.itoo.authority.cache.RedisCacheManager”>  
  96.         <property name=“redisManager” ref=“redisManager” />  
  97.     </bean>  
  98.     <!– 自定義cacheManager –>  
  99.     <bean id=“redisCache” class=“com.tgb.itoo.authority.cache.RedisCache”>  
  100.         <constructor-arg ref=“redisManager”></constructor-arg>  
  101.     </bean>  
  102.   
  103.     <bean id=“redisManager” class=“com.tgb.itoo.authority.cache.RedisManager”></bean>  
  104.   
  105.     <!– 緩存管理器redis-end-李社河-2015年4月14日 –>  
  106.   
  107.   
  108.   
  109.     <!– session會話存儲的實現類 –>  
  110.     <bean id=“redisShiroSessionDAO” class=“com.tgb.itoo.authority.cache.RedisSessionDAO”>  
  111.         <property name=“redisManager” ref=“redisManager” />  
  112.     </bean>  
  113.   
  114.   
  115.   
  116.     <!– sessionManager –>  
  117.     <!– session管理器 –>  
  118.     <bean id=“sessionManager”  
  119.         class=“org.apache.shiro.web.session.mgt.DefaultWebSessionManager”>  
  120.         <!– 設置全局會話超時時間,默認30分鐘(1800000) –>  
  121.         <property name=“globalSessionTimeout” value=“1800000” />  
  122.         <!– 是否在會話過期後會調用SessionDAO的delete方法刪除會話 默認true –>  
  123.         <property name=“deleteInvalidSessions” value=“true” />  
  124.   
  125.         <!– 會話驗證器調度時間 –>  
  126.         <property name=“sessionValidationInterval” value=“1800000” />  
  127.   
  128.         <!– session存儲的實現 –>  
  129.         <property name=“sessionDAO” ref=“redisShiroSessionDAO” />  
  130.         <!– sessionIdCookie的實現,用於重寫覆蓋容器默認的JSESSIONID –>  
  131.         <property name=“sessionIdCookie” ref=“sharesession” />  
  132.         <!– 定時檢查失效的session –>  
  133.         <property name=“sessionValidationSchedulerEnabled” value=“true” />  
  134.   
  135.     </bean>  
  136.   
  137.   
  138.     <!– sessionIdCookie的實現,用於重寫覆蓋容器默認的JSESSIONID –>  
  139.     <bean id=“sharesession” class=“org.apache.shiro.web.servlet.SimpleCookie”>  
  140.         <!– cookie的name,對應的默認是 JSESSIONID –>  
  141.         <constructor-arg name=“name” value=“SHAREJSESSIONID” />  
  142.         <!– jsessionId的path爲 / 用於多個系統共享jsessionId –>  
  143.         <property name=“path” value=“/” />  
  144.         <property name=“httpOnly” value=“true”/>  
  145.     </bean>  
  146.   
  147.   
  148.   
  149.   
  150.   
  151.   
  152.   
  153.     <!– 第一:shiro於數據交互的類 ,自己寫的類的實現-ShiroRealmBean自己重寫的類的實現 –>  
  154.     <bean id=“shiroRealm” class=“com.tgb.itoo.authority.service.ShiroRealmBean”>  
  155.         <property name=“defaultRoles” value=“user”></property>  
  156.   
  157.         <!– 注入自己實現的類,授權的過程-PermissionManager是雲平臺重寫的授權的過程,用戶Id->角色->資源->查找權限-李社河2015年4月15日 –>  
  158.         <property name=“permissionMgr” ref=“PermissionManager”></property>  
  159.         <property name=“casServerUrlPrefix” value={casServerUrlPrefix}"</span><span class="tag">&gt;</span><span class="tag">&lt;/</span><span class="tag-name">property</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">property</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">"casService"</span><span>&nbsp;</span><span class="attribute">value</span><span>=</span><span class="attribute-value">" {casService}”></property>  
  160.     </bean>  
  161.   
  162.     <bean id=“casSubjectFactory” class=“org.apache.shiro.cas.CasSubjectFactory” />  
  163.   
  164.     <!– shiro的自帶緩存管理器encahe –>  
  165.     <!– <bean id=”shiroEhcacheManager” class=”org.apache.shiro.cache.ehcache.EhCacheManager”> –>  
  166.     <!– <property name=“cacheManagerConfigFile” value=“classpath:config/ehcache-shiro.xml”   
  167.         /> –>  
  168.     <!– </bean> –>  
  169.   
  170.     <!– 開啓shiro的註解,需藉助SpringAOP掃描使用Shiro註解的類,並在必要時進行安全邏輯驗證 –>  
  171.     <bean  
  172.         class=“org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator”  
  173.         depends-on=“lifecycleBeanPostProcessor”></bean>  
  174.     <bean  
  175.         class=“org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor”>  
  176.         <property name=“securityManager” ref=“securityManager” />  
  177.     </bean>  
  178. </beans>  
  179. </span>  
<span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
    http://www.springframework.org/schema/tx  
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd"
    default-lazy-init="true">

    <!-- 註解支持 -->
    <context:annotation-config />
    <bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:config/shiro-cas.properties</value>
            </list>
        </property>
    </bean>



    <jee:local-slsb id="PermissionManager"
        jndi-name="java:global/itoo-authority-role-ear/itoo-authority-shiro-core-0.0.1-SNAPSHOT/PermissionManager!com.tgb.itoo.authority.service.ShiroBean"
        business-interface="com.tgb.itoo.authority.service.ShiroBean"></jee:local-slsb>

<!--     <jee:jndi-lookup id="PermissionManager" -->

<!--     jndi-name="ejb:itoo-authority-shiro-ear/itoo-authority-shiro-core-0.0.1-SNAPSHOT/PermissionManager!com.tgb.itoo.authority.service.ShiroBean" -->

<!--     lookup-on-startup="true" cache="true" environment-ref="evn"> -->

<!--     </jee:jndi-lookup> -->
    <!-- shiro過濾器 start -->
    <bean id="shiroSecurityFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"></property>
        <property name="loginUrl" value="${loginUrl}"></property>
        <property name="successUrl" value="${successUrl}"></property>
        <property name="filters">
            <map>
                <entry key="casFilter">
                    <bean class="org.apache.shiro.cas.CasFilter">
                        <!--配置驗證錯誤時的失敗頁面 /main 爲系統登錄頁面 -->
                        <property name="failureUrl" value="/message.jsp" />
                    </bean>
                </entry>
            </map>
        </property>
        <!-- 過濾器鏈,請求url對應的過濾器 -->
        <property name="filterChainDefinitions">
            <value>
                /message.jsp=anon
                /logout=logout
                /shiro-cas=casFilter
                /** =user
            </value>
        </property>
    </bean>
    <!-- shiro過濾器 end -->

    <!-- 保證實現shiro內部的生命週期函數bean的執行 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

    <!-- 第三:shiro管理中心類 start-李社河 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="shiroRealm"></property>
        <property name="sessionMode" value="http"></property>
        <property name="subjectFactory" ref="casSubjectFactory"></property>
        <!-- ehcahe緩存shiro自帶 -->
        <!-- <property name="cacheManager" ref="shiroEhcacheManager"></property> -->

        <!-- redis緩存 -->
        <property name="cacheManager" ref="redisCacheManager" />

        <!-- sessionManager -->
        <property name="sessionManager" ref="sessionManager"></property>
    </bean>


    <!-- 緩存管理器redis-start-李社河-2015年4月14日 -->

    <!-- sessionManager -->
    <!-- <bean id="sessionManager" -->
    <!-- class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> -->
    <!-- <property name="sessionDAO" ref="redisSessionDAO" /> -->
    <!-- </bean> -->

    <!-- 自定義redisManager-redis -->
    <bean id="redisCacheManager" class="com.tgb.itoo.authority.cache.RedisCacheManager">
        <property name="redisManager" ref="redisManager" />
    </bean>
    <!-- 自定義cacheManager -->
    <bean id="redisCache" class="com.tgb.itoo.authority.cache.RedisCache">
        <constructor-arg ref="redisManager"></constructor-arg>
    </bean>

    <bean id="redisManager" class="com.tgb.itoo.authority.cache.RedisManager"></bean>

    <!-- 緩存管理器redis-end-李社河-2015年4月14日 -->



    <!-- session會話存儲的實現類 -->
    <bean id="redisShiroSessionDAO" class="com.tgb.itoo.authority.cache.RedisSessionDAO">
        <property name="redisManager" ref="redisManager" />
    </bean>



    <!-- sessionManager -->
    <!-- session管理器 -->
    <bean id="sessionManager"
        class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        <!-- 設置全局會話超時時間,默認30分鐘(1800000) -->
        <property name="globalSessionTimeout" value="1800000" />
        <!-- 是否在會話過期後會調用SessionDAO的delete方法刪除會話 默認true -->
        <property name="deleteInvalidSessions" value="true" />

        <!-- 會話驗證器調度時間 -->
        <property name="sessionValidationInterval" value="1800000" />

        <!-- session存儲的實現 -->
        <property name="sessionDAO" ref="redisShiroSessionDAO" />
        <!-- sessionIdCookie的實現,用於重寫覆蓋容器默認的JSESSIONID -->
        <property name="sessionIdCookie" ref="sharesession" />
        <!-- 定時檢查失效的session -->
        <property name="sessionValidationSchedulerEnabled" value="true" />

    </bean>


    <!-- sessionIdCookie的實現,用於重寫覆蓋容器默認的JSESSIONID -->
    <bean id="sharesession" class="org.apache.shiro.web.servlet.SimpleCookie">
        <!-- cookie的name,對應的默認是 JSESSIONID -->
        <constructor-arg name="name" value="SHAREJSESSIONID" />
        <!-- jsessionId的path爲 / 用於多個系統共享jsessionId -->
        <property name="path" value="/" />
        <property name="httpOnly" value="true"/>
    </bean>







    <!-- 第一:shiro於數據交互的類 ,自己寫的類的實現-ShiroRealmBean自己重寫的類的實現 -->
    <bean id="shiroRealm" class="com.tgb.itoo.authority.service.ShiroRealmBean">
        <property name="defaultRoles" value="user"></property>

        <!-- 注入自己實現的類,授權的過程-PermissionManager是雲平臺重寫的授權的過程,用戶Id->角色->資源->查找權限-李社河2015年4月15日 -->
        <property name="permissionMgr" ref="PermissionManager"></property>
        <property name="casServerUrlPrefix" value="${casServerUrlPrefix}"></property>
        <property name="casService" value="${casService}"></property>
    </bean>

    <bean id="casSubjectFactory" class="org.apache.shiro.cas.CasSubjectFactory" />

    <!-- shiro的自帶緩存管理器encahe -->
    <!-- <bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> -->
    <!-- <property name="cacheManagerConfigFile" value="classpath:config/ehcache-shiro.xml" 
        /> -->
    <!-- </bean> -->

    <!-- 開啓shiro的註解,需藉助SpringAOP掃描使用Shiro註解的類,並在必要時進行安全邏輯驗證 -->
    <bean
        class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
        depends-on="lifecycleBeanPostProcessor"></bean>
    <bean
        class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager" />
    </bean>
</beans>
</span>


這樣第一個問題,session的共享問題我們就解決好了,下一篇介紹另一個問題,cache的共享問題。

發佈了0 篇原創文章 · 獲贊 19 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章