Spring Security(07)——缓存UserDetails

简介:        Spring Security提供了一个实现了可以缓存UserDetails的UserDetailsService实现类,CachingUserDetailsService。

       Spring Security提供了一个实现了可以缓存UserDetailsUserDetailsService实现类,CachingUserDetailsService。该类的构造接收一个用于真正加载UserDetailsUserDetailsService实现类。当需要加载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还为我们提供了一个基于EhcacheUserCache实现类,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;

    }

}

 

       从上述源码我们可以看到EhCacheBasedUserCache所引用的Ehcache是空的,所以,当我们需要对UserDetails进行缓存时,我们只需要定义一个Ehcache实例,然后把它注入给EhCacheBasedUserCache就可以了。接下来我们来看一下定义一个支持缓存UserDetailsCachingUserDetailsService的示例。

   <security:authentication-manager alias="authenticationManager">

      <!-- 使用可以缓存UserDetailsCachingUserDetailsService -->

      <security:authentication-provider

         user-service-ref="cachingUserDetailsService" />

   </security:authentication-manager>

   <!-- 可以缓存UserDetailsUserDetailsService -->

   <bean id="cachingUserDetailsService" class="org.springframework.security.config.authentication.CachingUserDetailsService">

      <!-- 真正加载UserDetailsUserDetailsService -->

      <constructor-arg ref="userDetailsService"/>

      <!-- 缓存UserDetailsUserCache -->

      <property name="userCache">

         <bean class="org.springframework.security.core.userdetails.cache.EhCacheBasedUserCache">

            <!-- 用于真正缓存的Ehcache对象 -->

            <property name="cache" ref="ehcache4UserDetails"/>

         </bean>

      </property>

   </bean>

   <!-- 将使用默认的CacheManager创建一个名为ehcache4UserDetailsEhcache对象 -->

   <bean id="ehcache4UserDetails" class="org.springframework.cache.ehcache.EhCacheFactoryBean"/>

   <!-- 从数据库加载UserDetailsUserDetailsService -->

   <bean id="userDetailsService"

      class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">

      <property name="dataSource" ref="dataSource" />

   </bean>

 

       在上面的配置中,我们通过EhcacheFactoryBean定义的Ehcache bean对象采用的是默认配置,其将使用默认的CacheManager,即直接通过CacheManager.getInstance()获取当前已经存在的CacheManager对象,如不存在则使用默认配置自动创建一个,当然这可以通过cacheManager属性指定我们需要使用的CacheManagerCacheManager可以通过EhCacheManagerFactoryBean进行定义。此外,如果没有指定对应缓存的名称,默认将使用beanName,在上述配置中即为ehcache4UserDetails,可以通过cacheName属性进行指定。此外,缓存的配置信息也都是使用的默认的。更多关于Spring使用Ehcache的信息可以参考我的另一篇文章《Spring使用Cache》。

 

(注:本文是基于Spring Security3.1.6所写)

 

 (注:原创文章,转载请注明出处。原文地址:http://elim.iteye.com/blog/2159871

目录
相关文章
|
3月前
|
缓存 NoSQL Java
【Azure Redis 缓存】示例使用 redisson-spring-boot-starter 连接/使用 Azure Redis 服务
【Azure Redis 缓存】示例使用 redisson-spring-boot-starter 连接/使用 Azure Redis 服务
|
7天前
|
存储 缓存 Java
Spring缓存注解【@Cacheable、@CachePut、@CacheEvict、@Caching、@CacheConfig】使用及注意事项
Spring缓存注解【@Cacheable、@CachePut、@CacheEvict、@Caching、@CacheConfig】使用及注意事项
40 2
|
2月前
|
缓存 Java 开发工具
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
三级缓存是Spring框架里,一个经典的技术点,它很好地解决了循环依赖的问题,也是很多面试中会被问到的问题,本文从源码入手,详细剖析Spring三级缓存的来龙去脉。
169 24
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
|
4月前
|
安全 Java 数据安全/隐私保护
使用Spring Security实现细粒度的权限控制
使用Spring Security实现细粒度的权限控制
|
4月前
|
安全 Java 数据库
实现基于Spring Security的权限管理系统
实现基于Spring Security的权限管理系统
|
4月前
|
安全 Java 数据安全/隐私保护
解析Spring Security中的权限控制策略
解析Spring Security中的权限控制策略
|
2月前
|
存储 缓存 Java
在Spring Boot中使用缓存的技术解析
通过利用Spring Boot中的缓存支持,开发者可以轻松地实现高效和可扩展的缓存策略,进而提升应用的性能和用户体验。Spring Boot的声明式缓存抽象和对多种缓存技术的支持,使得集成和使用缓存变得前所未有的简单。无论是在开发新应用还是优化现有应用,合理地使用缓存都是提高性能的有效手段。
36 1
|
3月前
|
缓存 NoSQL Java
SpringBoot的三种缓存技术(Spring Cache、Layering Cache 框架、Alibaba JetCache 框架)
Spring Cache 是 Spring 提供的简易缓存方案,支持本地与 Redis 缓存。通过添加 `spring-boot-starter-data-redis` 和 `spring-boot-starter-cache` 依赖,并使用 `@EnableCaching` 开启缓存功能。JetCache 由阿里开源,功能更丰富,支持多级缓存和异步 API,通过引入 `jetcache-starter-redis` 依赖并配置 YAML 文件启用。Layering Cache 则提供分层缓存机制,需引入 `layering-cache-starter` 依赖并使用特定注解实现缓存逻辑。
825 1
SpringBoot的三种缓存技术(Spring Cache、Layering Cache 框架、Alibaba JetCache 框架)
|
3月前
|
缓存 Java Spring
Spring缓存实践指南:从入门到精通的全方位攻略!
【8月更文挑战第31天】在现代Web应用开发中,性能优化至关重要。Spring框架提供的缓存机制可以帮助开发者轻松实现数据缓存,提升应用响应速度并减少服务器负载。通过简单的配置和注解,如`@Cacheable`、`@CachePut`和`@CacheEvict`,可以将缓存功能无缝集成到Spring应用中。例如,在配置文件中启用缓存支持并通过`@Cacheable`注解标记方法即可实现缓存。此外,合理设计缓存策略也很重要,需考虑数据变动频率及缓存大小等因素。总之,Spring缓存机制为提升应用性能提供了一种简便快捷的方式。
48 0
|
3月前
|
缓存 NoSQL Java
惊!Spring Boot遇上Redis,竟开启了一场缓存实战的革命!
【8月更文挑战第29天】在互联网时代,数据的高速读写至关重要。Spring Boot凭借简洁高效的特点广受开发者喜爱,而Redis作为高性能内存数据库,在缓存和消息队列领域表现出色。本文通过电商平台商品推荐系统的实战案例,详细介绍如何在Spring Boot项目中整合Redis,提升系统响应速度和用户体验。
60 0