一般来讲,记住密码的基本处理,就是把用户的一些基本信息(密码)存入浏览器的Cookie,下次登录的时候优先验证Cookie,后端做处理;以此来实现记住密码的功能!使用shiro自带的RememberMe功能,使用起来比较简单,只需简单的配置。
需注意一点的是,网站如果对安全性要求比较高的,一般都不建议有记住密码的功能! 因为Cookie是保存在本机电脑浏览器里,不排除其他用户能使用此电脑,拷走Cookie,导入其他电脑继续使用您的账号登录!
shiro实现了身份验证和权限验证。但是,如果我们登录之后多次访问http://localhost:8080/userInfo/userDel
的话,会发现权限验证会每次都执行一次。这是有问题的,因为像用户的权限这些我们提供给shiro一次就够了。
下面,我们开始给shiro添加缓存支持:
1.添加依赖
<!-- shiro ehcache --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-ehcache</artifactId><version>1.2.2</version></dependency><!--包含支持UI模版(Velocity,FreeMarker,JasperReports),邮件服务,脚本服务(JRuby),缓存Cache(EHCache),任务计划Scheduling(uartz)。--><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency>
2.注入缓存
在com.example.demo.config.Shiro.ShiroConfiguration
中添加以下方法。
@Beanpublic EhCacheManager ehCacheManager() {System.out.println("ShiroConfiguration.getEhCacheManager()");EhCacheManager ehCacheManager = new EhCacheManager();ehCacheManager.setCacheManagerConfigFile("classpath:config/ehcache-shiro.xml");return ehCacheManager;}
将缓存对象注入到SecurityManager
中:
@Beanpublic SecurityManager securityManager() {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setRealm(myShiroRealm());securityManager.setCacheManager(ehCacheManager()); //注入缓存对象。return securityManager;}
3.添加配置文件
在src/main/resouces/config中添加ehcache-shiro.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="es"><diskStore path="java.io.tmpdir"/><!--name:缓存名称。maxElementsInMemory:缓存最大数目maxElementsOnDisk:硬盘最大缓存个数。eternal:对象是否永久有效,一但设置了,timeout将不起作用。overflowToDisk:是否保存到磁盘,当系统当机时timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。clearOnFlush:内存数量最大时是否清除。memoryStoreEvictionPolicy:Ehcache的三种清空策略;FIFO,first in first out,这个是大家最熟的,先进先出。LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。--><defaultCachemaxElementsInMemory="10000"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"overflowToDisk="false"diskPersistent="false"diskExpiryThreadIntervalSeconds="120"/><!-- 登录记录缓存锁定10分钟 --><cache name="passwordRetryCache"maxEntriesLocalHeap="2000"eternal="false"timeToIdleSeconds="3600"timeToLiveSeconds="0"overflowToDisk="false"statistics="true"></cache></ehcache>
启动项目,再多次访问http://localhost:8080/userInfo/userDel
,这时候只会在后台打印一次配置权限的信息了,说明shiro缓存起了作用。
---------------------下面我们开始配置记住密码-----------
1.在com.example.demo.config.Shiro.ShiroConfiguration
中加入下面两个方法:
//cookie对象;@Beanpublic SimpleCookie rememberMeCookie() {System.out.println("ShiroConfiguration.rememberMeCookie()");//这个参数是cookie的名称,对应前端的checkbox的name = rememberMeSimpleCookie simpleCookie = new SimpleCookie("rememberMe");//<!-- 记住我cookie生效时间30天 ,单位秒;-->simpleCookie.setMaxAge(259200);return simpleCookie;}//cookie管理对象;@Beanpublic CookieRememberMeManager cookieRememberMeManager() {System.out.println("ShiroConfiguration.rememberMeManager()");CookieRememberMeManager manager = new CookieRememberMeManager();manager.setCookie(rememberMeCookie());return manager;}
将rememberMeManager注入到SecurityManager中
@Beanpublic SecurityManager securityManager() {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setRealm(myShiroRealm());securityManager.setCacheManager(ehCacheManager());securityManager.setRememberMeManager(cookieRememberMeManager()); //注入rememberMeManager;return securityManager;}
在ShiroFilterFactoryBean
中添加记住我过滤器user
,添加user
过滤器的资源在记住我或认证之后就可以直接访问了。
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
...filterChainDefinitionMap.put("/index", "user");filterChainDefinitionMap.put("/", "user");
....
最后,在login.html页面添加记住我单选框
<P><input type="checkbox" name="rememberMe" />记住我</P>
启动项目,正常登录后关闭浏览器,再打开浏览器输入http://localhost:8080/index
,这时候就可以直接访问index页面,不需要再登录了。