shiro登陆+Ehcache缓存技术

1.先上shiro.xml中的配置      将缓存管理器配置进去

    

<!-- 缓存管理器 使用Ehcache实现 -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/>
</bean>
<!-- 自定义凭证匹配器-->
<bean id="credentialsMatcher" class="cn.cjq.util.shiro.RetryLimitHashedCredentialsMatcher">
<constructor-arg ref="cacheManager"/>
<property name="hashAlgorithmName" value="md5"/>
<property name="hashIterations" value="1"/>
<property name="storedCredentialsHexEncoded" value="true"/>
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- Single realm app. If you have multiple realms, use the 'realms' property instead. -->
<property name="realm" ref="myShiroRealm"/>
<property name="sessionManager" ref="sessionManager"/>
<property name="cacheManager" ref="cacheManager"/>
<!-- 记住我 -->
<property name="rememberMeManager" ref="rememberMeManager"/>
</bean>
--------------------------------------------------------------------------------------------------------
2.上ehcache.xml配置文件 记录缓存参数
<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="shirocache">

<diskStore path="java.io.tmpdir"/>

<defaultCache
name="defaut"
maxElementsInMemory="5"
eternal="false"
timeToIdleSeconds="20"
timeToLiveSeconds="20"
overflowToDisk="false"
diskPersistent="false"
memoryStoreEvictionPolicy="LRU"
/>

<!-- 登录记录缓存 锁定10分钟 -->
<cache name="passwordRetryCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
>
</cache>
<!-- 授权缓存 -->
<cache name="authorizationCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
>
</cache>
<!-- 认证缓存 -->
<cache name="authenticationCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
>
</cache>

<cache name="shiro-activeSessionCache"
maxEntriesLocalHeap="10000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
>
</cache>


</ehcache>
-----------------------------------------------------------------------------------------------------------------------
3.自定义凭证匹配器 缓存使用实例 密码错误大于五次抛ExcessiveAttemptsException异常
package cn.cjq.util.shiro;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;

import java.util.concurrent.atomic.AtomicInteger;

public class RetryLimitHashedCredentialsMatcher extends
HashedCredentialsMatcher {
private Cache<String, AtomicInteger> passwordRetryCache;

public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) {
passwordRetryCache = cacheManager.getCache("passwordRetryCache");
}

@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
String username = (String)token.getPrincipal();
//retry count + 1
AtomicInteger retryCount = passwordRetryCache.get(username);
if(retryCount == null) {
retryCount = new AtomicInteger(0);
passwordRetryCache.put(username, retryCount);
}
if(retryCount.incrementAndGet() > 5) {
//if retry count > 5 throw
throw new ExcessiveAttemptsException();
}

boolean matches = super.doCredentialsMatch(token, info);
if(matches) {
//clear retry count
passwordRetryCache.remove(username);
}
return matches;
}
}

----------------------------------------------------------------------------------------------------------------------------
4.缓存实例 注入cacheManager
@Resource
private CacheManager cacheManager;
//获取
Cache<String, AtomicInteger> passwordRetryCache=cacheManager.getCache("passwordRetryCache");
//捕捉认证异常
catch (AuthenticationException e) {
//参数认证异常
return new Response("999999","输入参数有误,您还有" +(6-passwordRetryCache.get(userName).get())+"次机会重新输入!");
}

------------------------------------------------------------------------------------------------------

附录:AtomicInteger类 AtomicInteger是一个提供原子操作的Integer类,通过线程安全的方式操作加减。十分适合高并发情况下的使用
在使用Integer的时候,必须加上synchronized保证不会出现并发线程同时访问的情况,而在AtomicInteger中却不用加上synchronized,在这里AtomicInteger是提供原子操作的。
AtomicInteger运算
  1. public class Test {  
  2.     public static void main(String[] args) {  
  3.         AtomicInteger integer = new AtomicInteger();  
  4.         integer.set(1);  
  5.         int i = integer.get(); //获得值  
  6.         System.out.println(i);  
  7.         i = integer.incrementAndGet(); //先+1,然后在返回值,相当于++i  
  8.         System.out.println(i);  
  9.         i = integer.getAndIncrement();//先返回值,然后在+1,相当于i++  
  10.         System.out.println(i);  
  11.         i = integer.get();  
  12.         System.out.println(i);  
  13.         i = integer.decrementAndGet();//先-1,然后在返回值,相当于--i  
  14.         System.out.println(i);  
  15.         i = integer.getAndDecrement();//先返回值,然后在-1,相当于i--  
  16.         System.out.println(i);  
  17.         i = integer.get();  
  18.         System.out.println(i);//1  
  19.         i = integer.addAndGet(1);//先+n,然后在返回值,  
  20.         System.out.println(i);  
  21.         i = integer.getAndAdd(1);//先返回,然后+n  
  22.         System.out.println(i);  
  23.         i = integer.get();  
  24.         System.out.println(i);  
  25.     }  
  26. }  
----------------------------------------------------------------------------------------------------------------------------------------------
附录2
主要的特性有:
1. 快速
2. 简单
3. 多种缓存策略
4. 缓存数据有两级:内存和磁盘,因此无需担心容量问题
5. 缓存数据会在虚拟机重启的过程中写入磁盘
6. 可以通过RMI、可插入API等方式进行分布式缓存
7. 具有缓存和缓存管理器的侦听接口
8. 支持多缓存管理器实例,以及一个实例的多个缓存区域
9. 提供Hibernate的缓存实现
 
ehcache.xml:里面的注释写的很清楚了。
<diskStore>   : 当内存缓存中对象数量超过maxElementsInMemory时,将缓存对象写到磁盘缓存中(需对象实现序列化接口)  
<diskStore path="">     : 用来配置磁盘缓存使用的物理路径,Ehcache磁盘缓存使用的文件后缀名是*.data和*.index  
name : "缓存名称,cache的唯一标识(ehcache会把这个cache放到HashMap里)  
maxElementsInMemory  : 缓存最大个数。
eternal="false"  : 对象是否永久有效,一但设置了,timeout将不起作用。 (必须设置)
maxEntriesLocalHeap="1000"  : 堆内存中最大缓存对象数,0没有限制(必须设置)
maxEntriesLocalDisk= "1000"   : 硬盘最大缓存个数。
overflowToDisk="false"   : 当缓存达到maxElementsInMemory值是,是否允许溢出到磁盘(必须设置)(内存不足时,是否启用磁盘缓存。)
diskSpoolBufferSizeMB  : 这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
diskPersistent="false"  : 磁盘缓存在JVM重新启动时是否保持(默认为false)
timeToIdleSeconds="0"  : 导致元素过期的访问间隔(秒为单位),即当缓存闲置n秒后销毁。 当eternal为false时,这个属性才有效,0表示可以永远空闲,默认为0
 timeToLiveSeconds="600"   : 元素在缓存里存在的时间(秒为单位),即当缓存存活n秒后销毁. 0 表示永远存在不过期
memoryStoreEvictionPolicy="LFU" : 当达到maxElementsInMemory时,如何强制进行驱逐默认使用"最近使用(LRU)"策略,其它还有先入先出FIFO,最少使用LFU,较少使用LRU
 diskExpiryThreadIntervalSeconds :磁盘失效线程运行时间间隔,默认是120秒。
 clearOnFlush   : 内存数量最大时是否清除。




原文地址:https://www.cnblogs.com/1234cjq/p/8176439.html