Spring Security 缓存 UserDetails
admin
2023-07-30 19:53:50
0

缓存 UserDetails

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;
    }
}

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

 
      
      
   
   
   
      
      
      
      
         
            
            
         
      
   
   
   
   
   
      
   

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

相关内容

AccessDecisio...
使用新的授权模型在Spring Security 6.x中,Acc...
2024-05-16 01:22:38
Spring Securi...
Spring Security 的权限鉴定是由 AccessDec...
2023-07-30 19:53:56
Spring Securi...
session 管理 Spring Security 通过 htt...
2023-07-30 19:53:55
Spring Securi...
Remember-Me 功能 概述 Remember-Me 是指网...
2023-07-30 19:53:55
Spring Securi...
匿名认证 对于匿名访问的用户,Spring Security 支持...
2023-07-30 19:53:54
Spring Securi...
退出登录 logout 要实现退出登录的功能我们需要在 http ...
2023-07-30 19:53:52

热门资讯

QQ音乐提示代理模式可能无法正... QQ音乐提示代理模式可能无法正常访问,如上图所示,是怎么回事呢? 这个可能和你的网络设置有关系,首先...
frp内网穿透配置 HTTP ... HTTP 类型的代理相比于 TCP 类型,不仅在服务端只需要监听一个额外的端口 vhost_http...
当前安全设置不允许下载该文件的... 今天新装了一台服务器 在服务器上准备安装下载chrome浏览器,结果发现不能下载,提示当前安全设置不...
premiere提示“项目看来... 有可能是pr的版本不一致造成的 可以选择 换个pr的版本就好了,或者换台电脑,千万不要乱删 或者新建...
为什么我的局域网传输最高速度只... 网络传输的最高速度取决于你网络中瓶颈最小值。 比如传输的两台电脑 路由器等一切传输设备的限制。 这个...
安装CAD提示错误1327 驱... 安装的cad中出现错误1327,安装中出现问题,停止安装,请插入某驱动器“错误1327驱动器无效:D...
经常被陌生人拉进一堆莫名奇妙的... 经常莫名其妙拉进去陌生的QQ群,大部分都是炒股之类的。 这个怎么屏蔽? 首先打开手机QQ群,进入设置...
电脑上如何更新视频号 微信推出视频号之后,受到不少的关注,之前一直没有重视。现在打算测试一下。 正好最近视频号助手也开始内...
安装AutoCAD提示错误13... 今天安装AutoCAD提示错误1327,驱动器F:无效 第一次遇到这种情况 上网搜索了很多解决办法都...
抖音uid在哪里查看? 抖音uid在哪里,可进入手机抖音设置页面里查看uid信息。 1、首先打开手机上的抖音软件,点击右下角...