zoukankan      html  css  js  c++  java
  • Spring-Security (学习记录六)--采用ehcache缓存UserDetails

    参考: http://www.mincoder.com/article/3506.shtml

    1. spring-security提供了缓存UserDetails的UserDetailsService实现类。

    • Spring Security提供了一个实现了可以缓存UserDetails的UserDetailsService实现类,CachingUserDetailsService。该类的构造接收一个用于真正加载UserDetails的UserDetailsService实现类。当需要加载UserDetails时,其首先会从缓存中获取,如果缓存中没有对应的UserDetails存在,则使用持有的UserDetailsService实现类进行加载,然后将加载后的结果存放在缓存中。UserDetails与缓存的交互是通过UserCache接口来实现的。CachingUserDetailsService默认拥有UserCache的一个空实现引用,NullUserCache。以下是CachingUserDetailsService的类定义。
    
    public class CachingUserDetailsService implements UserDetailsService {
    
        private UserCache userCache = new NullUserCache();
    
        private final UserDetailsService delegate;
    
     
    
        CachingUserDetailsService(UserDetailsService delegate) {
    
            this.delegate = delegate;
    
        }
    
     
    
        public UserCache getUserCache() {
    
            return userCache;
    
        }
    
     
    
        public void setUserCache(UserCache userCache) {
    
            this.userCache = userCache;
    
        }
    
     
    
        public UserDetails loadUserByUsername(String username) {
    
            UserDetails user = userCache.getUserFromCache(username);
    
     
    
            if (user == null) {
    
                user = delegate.loadUserByUsername(username);
    
            }
    
     
    
            Assert.notNull(user, "UserDetailsService " + delegate + " returned null for username " + username + ". " +
    
                    "This is an interface contract violation");
    
     
    
            userCache.putUserInCache(user);
    
     
    
            return user;
    
        }
    
    }
    
    
    
    
    • 我们可以看到当缓存中不存在对应的UserDetails时将使用引用的UserDetailsService类型的delegate进行加载。加载后再把它存放到Cache中并进行返回。除了NullUserCache之外,Spring Security还为我们提供了一个基于Ehcache的UserCache实现类,EhCacheBasedUserCache,其源码如下所示。
    
    public class EhCacheBasedUserCache implements UserCache, InitializingBean {
    
     
    
        private static final Log logger = LogFactory.getLog(EhCacheBasedUserCache.class);
    
     
    
        private Ehcache cache;
    
     
    
        public void afterPropertiesSet() throws Exception {
    
            Assert.notNull(cache, "cache mandatory");
    
        }
    
     
    
        public Ehcache getCache() {
    
            returncache;
    
        }
    
     
    
        public UserDetails getUserFromCache(String username) {
    
            Element element = cache.get(username);
    
            if (logger.isDebugEnabled()) {
    
                logger.debug("Cache hit: " + (element != null) + "; username: " + username);
    
            }
    
            if (element == null) {
    
                returnnull;
    
            } else {
    
                return (UserDetails) element.getValue();
    
            }
    
        }
    
     
    
        public void putUserInCache(UserDetails user) {
    
            Element element = new Element(user.getUsername(), user);
    
            if (logger.isDebugEnabled()) {
    
                logger.debug("Cache put: " + element.getKey());
    
            }
    
            cache.put(element);
    
        }
    
     
    
        public void removeUserFromCache(UserDetails user) {
    
            if (logger.isDebugEnabled()) {
    
                logger.debug("Cache remove: " + user.getUsername());
    
            }
    
            this.removeUserFromCache(user.getUsername());
    
        }
    
     
    
        public void removeUserFromCache(String username) {
    
            cache.remove(username);
    
        }
    
     
    
        public void setCache(Ehcache cache) {
    
            this.cache = cache;
    
        }
    
    }
    
    
    
    

    2. 通过配置来完成缓存 UserDetails (使用ehcache)

    • 从上述源码我们可以看到EhCacheBasedUserCache所引用的Ehcache是空的,所以,当我们需要对UserDetails进行缓存时,我们只需要定义一个Ehcache实例,然后把它注入给EhCacheBasedUserCache就可以了。接下来我们来看一下定义一个支持缓存UserDetails的CachingUserDetailsService的示例。
    
    
        <!-- 认证管理器,配置了管理员与角色的关系  -->
        <security:authentication-manager alias="authenticationManager">
            <!-- 配置账号密码所属的角色  角色以 ROLE_开头,为spring获取名称的标识 (xml方式的才需要)
                user-service-ref="accountService" : 配置启动数据库方式获取用户和角色,xml失效
             -->
            <security:authentication-provider user-service-ref="cachingUserDetailsService">
                <!-- 密码采用md5加密  -->
                <security:password-encoder hash="md5" />
            </security:authentication-provider>
        </security:authentication-manager>
        
        
        <bean id="cachingUserDetailsService" class="org.springframework.security.config.authentication.CachingUserDetailsService">
            <!-- 真正加载UserDetails的UserDetailsService -->
            <constructor-arg ref="accountService"/>
            <!-- 缓存UserDetails的UserCache -->
            <property name="userCache">
                <bean class="org.springframework.security.core.userdetails.cache.EhCacheBasedUserCache">
                   <!-- 用于真正缓存的Ehcache对象 -->
                   <property name="cache" ref="ehcache4UserDetails"/>
                </bean>
            </property>
           </bean>
        
        <!-- 将使用默认的CacheManager创建一个名为ehcache4UserDetails的Ehcache对象 -->
        <bean id="ehcache4UserDetails" class="org.springframework.cache.ehcache.EhCacheFactoryBean"/>
    

    3. 引入ehcache

    • pom.xml中引入
    <!-- ehcache需要的依赖 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>3.2.5.RELEASE</version>
    </dependency>
    <!-- 加入ehcache -->
    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache</artifactId>
        <version>2.7.4</version>
    </dependency>  
    
    • 添加ehcache.xml配置文件(详见附件)

    • 项目中添加spring-ehcache.xml (详见附件)

    <!-- 开启spring缓存 -->
    <cache:annotation-driven cache-manager="cacheManager" />
    <bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:configLocation="classpath:ehcache.xml" p:shared="false" />
    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cacheManager-ref="cacheManagerFactory" />
    </beans>
    

    这样。缓存UserDetails就成功了。

    百度云链接:http://pan.baidu.com/s/1c2FmMQG 密码:vnov

  • 相关阅读:
    角色扮演游戏引擎的设计原理
    游戏服务器架构
    小谈网络游戏同步
    What is the single most influential book every programmer should read?
    Research Scientists and Engineers
    关于为什么不推荐使用用户定义表类型的说明
    程序员必须遵守的编程原则
    CacheStrategy缓存
    正能量
    MEF 和 MAF
  • 原文地址:https://www.cnblogs.com/linhp/p/5817070.html
Copyright © 2011-2022 走看看