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

  • 相关阅读:
    【Leetcode】【Easy】Remove Duplicates from Sorted List
    【Leetcode】【Easy】Pascal's Triangle II
    【Leetcode】【Easy】Pascal's Triangle
    【Leetcode】【Easy】Binary Tree Level Order Traversal II
    【Leetcode】【Easy】Binary Tree Level Order Traversal
    【Leetcode】【Easy】Maximum Depth of Binary Tree
    【Leetcode】【Easy】Minimum Depth of Binary Tree
    【Leetcode】【Easy】Balanced Binary Tree
    【Leetcode】【Easy】Symmetric Tree
    如何使用Action.Invoke()触发一个Storyboard
  • 原文地址:https://www.cnblogs.com/linhp/p/5817070.html
Copyright © 2011-2022 走看看