参考: 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

Spring-Security (学习记录六)--采用ehcache缓存UserDetails的更多相关文章

  1. Spring Security 学习记录

    一.核心拦截器详细说明 1.WebAsyncManagerIntegrationFilter 根据请求封装获取WebAsyncManager 从WebAsyncManager获取/注册Security ...

  2. [转]Spring Security学习总结一

    [总结-含源码]Spring Security学习总结一(补命名空间配置) Posted on 2008-08-20 10:25 tangtb 阅读(43111) 评论(27)  编辑  收藏 所属分 ...

  3. [转]Spring Security学习总结二

    原文链接: http://www.blogjava.net/redhatlinux/archive/2008/08/20/223148.html http://www.blogjava.net/red ...

  4. SpringBoot + Spring Security 学习笔记(三)实现图片验证码认证

    整体实现逻辑 前端在登录页面时,自动从后台获取最新的验证码图片 服务器接收获取生成验证码请求,生成验证码和对应的图片,图片响应回前端,验证码保存一份到服务器的 session 中 前端用户登录时携带当 ...

  5. Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客

    ==他的博客应该不错,没有细看 Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客 http://blog.csdn.net/u012706811/article/det ...

  6. Spring security 学习 (自助者,天助之!)

    自己努力,何必要强颜欢笑的求助别人呢?  手心向下不求人! Spring security学习有进展哦: 哈哈! 1.页面都是动态生产的吧! 2.设置权限:  a:pom.xml配置jar包 b:cr ...

  7. SpringBoot + Spring Security 学习笔记(五)实现短信验证码+登录功能

    在 Spring Security 中基于表单的认证模式,默认就是密码帐号登录认证,那么对于短信验证码+登录的方式,Spring Security 没有现成的接口可以使用,所以需要自己的封装一个类似的 ...

  8. 我的Spring Boot学习记录(二):Tomcat Server以及Spring MVC的上下文问题

    Spring Boot版本: 2.0.0.RELEASE 这里需要引入依赖 spring-boot-starter-web 这里有可能有个人的误解,请抱着怀疑态度看. 建议: 感觉自己也会被绕晕,所以 ...

  9. spring security 学习资料

    spring security 学习资料 网址 Spring Security 文档参考手册中文版 https://springcloud.cc/spring-security.html

随机推荐

  1. 【LeetCode 4】寻找两个有序数组的中位数

    题目链接 [题解] 假设在两个有序的序列中找第k小的数字. 那么我们先定位第一个序列中的第k/2个数字(不足则取最边上的那个数字)记下标为i1 然后定位第二个序列中的第k/2个数字(同样不足则取最边上 ...

  2. vue-element-admin打包后白屏的问题

    publicPath: './',

  3. 使用HBuilder编辑器进行真机调试运行时提示Waiting for debugger!

    在使用HBuilder编辑器创建mui项目进行真机调试的时候,手机总是提示Waiting for debugger! 现在终于找到了解决办法: 手机 设置 -> 开发人员选项 -> USB ...

  4. SP7258 SUBLEX - Lexicographical Substring Search(后缀自动机)

    传送门 解题思路 首先建\(sam\),然后在拓扑序上\(dp\)一下,把每个点的路径数算出来,然后统计答案时就在自动机上\(dfs\)一下,仿照平衡树那样找第\(k\)小. 代码 #include& ...

  5. AcWing 202. 最幸运的数字 (欧拉定理)打卡

    8是中国的幸运数字,如果一个数字的每一位都由8构成则该数字被称作是幸运数字. 现在给定一个正整数L,请问至少多少个8连在一起组成的正整数(即最小幸运数字)是L的倍数. 输入格式 输入包含多组测试用例. ...

  6. element not visible的解决方法

    抛出异常主题为element not visible主要有一下三个方面的原因. 元素之间存在逻辑关系,比如你要选择地址时,中国选择完毕之后,才能选择北京.如果想直接一步到位,则会出现element n ...

  7. 二叉树总结及部分Lintcode题目分析 1

    1. 遍历问题 Preorder / Inorder / Postorder preorder: root left right inorder: left root right postorder: ...

  8. react map循环数据 死循环

    项目条件:react es6 antidesign 已在commonState中获取到list,但是在循环map填充DOM的时候陷入死循环. 原因:因为是子组件 ,在父组件请求数据的时候 有个时差过程 ...

  9. CSS 案例学习

    1.样式 display:inline-block;可改变a标签,合其可定义宽高 2.a:hover表示鼠标经过 3.background:url(110.png) bottom 表示:给链接一个图片 ...

  10. python不同包之间调用时提示文件模块不存在的问题

    python对于跨包调用函数时,经常会提示模块不存在的问题,主要是python程序执行时,搜索路径导致的,python程序执行的路径依次是: (1)程序根目录(2)环境变量(3)标准库目标(D:\Py ...