zoukankan      html  css  js  c++  java
  • 在shiro中,登录限制次数

    方法如下,

    自定义一个匹配器,然后把用户名密码写入ehcache中,然后再读出,判断次数

    首先mavne引入jar坐标

    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-ehcache</artifactId>
        <version>1.2.4</version>
    </dependency>

    第一步,定义匹配器

    package cn.taotao.shiro.service;
    
    import java.util.concurrent.atomic.AtomicInteger;
    
    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;
    
    public class MyHashedCredentialsMatcher extends HashedCredentialsMatcher {
    
        
        private Cache<String, AtomicInteger> passwordRetryCache;
        public MyHashedCredentialsMatcher(CacheManager cacheManager) {
            passwordRetryCache = cacheManager.getCache("passwordRetryCache");
        }
    
        @Override
        public boolean doCredentialsMatch(AuthenticationToken token,
                                          AuthenticationInfo info) {
            System.out.println("docredentialsmatch......");
            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
                System.out.println("username: " + username + " tried to login more than 5 times in period");
                throw new ExcessiveAttemptsException("username: " + username + " tried to login more than 5 times in period");
            }
    
            boolean matches = super.doCredentialsMatch(token, info);
            if (matches) {
                // clear retry count
                passwordRetryCache.remove(username);
            }
            return matches;
        }
    }

    第二步,配置ehache的配置文件,passwordRetryCache为本例修改部分

    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
        <!-- 磁盘保存路径 -->
        <diskStore path="D:44ehcache" />
    
        <defaultCache maxElementsInMemory="10000"
            maxElementsOnDisk="10000000" eternal="false" overflowToDisk="true"
            timeToIdleSeconds="120" timeToLiveSeconds="120"
            diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU">
        </defaultCache>
         <cache name="passwordRetryCache" eternal="false"  
               maxEntriesLocalHeap="2000"
               timeToIdleSeconds="3600" timeToLiveSeconds="0" overflowToDisk="false"
               statistics="true">
        </cache>
    </ehcache>

    第三步,配置spring文件,让其加载匹配器,注释掉的部分为之前内容,引用的matcher为新加的内容。在新加入的mathcher中,引用了cachemanager,这个改为自己的ehcache的配置名称。

      <!-- 
            3. 配置 Realm 
            3.1 直接配置实现了 org.apache.shiro.realm.Realm 接口的 bean
        -->     
        <bean id="jdbcRealm" class="cn.taotao.shiro.realms.ShiroRealm">
    <!--         <property name="credentialsMatcher"> -->
    <!--             <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> -->
    <!--                 <property name="hashAlgorithmName" value="MD5"></property> -->
    <!--                 <property name="hashIterations" value="1024"></property> -->
    <!--             </bean> -->
    <!--         </property> -->
             <property name="credentialsMatcher" ref="credentialsMatcher"/>
        </bean>
        
        <bean id="credentialsMatcher" class="cn.taotao.shiro.service.MyHashedCredentialsMatcher">
            <constructor-arg ref="cacheManager"/> 
            <property name="storedCredentialsHexEncoded" value="true"/> 
            <property name="hashAlgorithmName" value="MD5"></property> 
            <property name="hashIterations" value="1024"></property> 
     </bean>

    第四步,在前台控制页面加入重新登录次数过多的提示

        @RequestMapping("/login")
        public String login(@RequestParam("username") String username, 
            @RequestParam("password") String password,Map<String ,Object> map) {    
            
            Subject currentUser = SecurityUtils.getSubject();
            
            if (!currentUser.isAuthenticated()) {
                // 把用户名和密码封装为 UsernamePasswordToken 对象
                UsernamePasswordToken token = new UsernamePasswordToken(username, password);
    
                // rememberme
                token.setRememberMe(true);
                try {
                    System.out.println("1. " + token.hashCode());
                    // 执行登录. 
                    currentUser.login(token);
                   
                    return "redirect:/index.jsp";
                } 
     
                // 密码重试过多的提示
                catch(ExcessiveAttemptsException ee){
                    System.out.println("重试次数过多,请稍后再试");
                    map.put("errors","重试次数过多,请稍后再试!");
                    return "login";
                }
    // 所有认证登录失败的提示
    catch (AuthenticationException ae) { //unexpected condition? error? System.out.println("登录失败: " + ae.getMessage()); map.put("errors","Login errors!"); // error.addError(new FieldError("admin", "password", "登录失败")); return "login"; } } return "redirect:/unauthorized.jsp"; }
  • 相关阅读:
    JavaScript--微博发布效果
    JavaScript--模拟百度搜索下拉li
    JavaScript--for in循环访问属性用"."和[ ]的区别
    JavaScript--函数中()的作用
    JavaScript--时间日期格式化封装
    【网络】Vmware虚拟机下三种网络模式配置
    【IP】DHCP介绍
    【Shell】ps -ef 和ps aux
    【基础】Pipeline
    【时间】Unix时间戳
  • 原文地址:https://www.cnblogs.com/sdgtxuyong/p/12154892.html
Copyright © 2011-2022 走看看