zoukankan      html  css  js  c++  java
  • 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   : 内存数量最大时是否清除。




  • 相关阅读:
    创建自定义 AJAX 客户端控件(msdn)
    使用jquery的blockui插件显示弹出层
    Sql Server高手必备
    Js获取当前日期时间及其它操作
    在VS2010中创建自定义的代码段
    存储过程分页
    完美辨析各种高度区别
    程序员必备的正则表达式
    Sql日期格式化
    C#调用Quartz实例代码
  • 原文地址:https://www.cnblogs.com/1234cjq/p/8176439.html
Copyright © 2011-2022 走看看