• 登陆失败账号锁定


    一、session

    public Object login(User user,HttpSession session) throws Exception {
            String username = user.getUsername();
            String password = user.getPassword();
            if(!checkLock(session, username)) {
                throw new CustomException(StatusCode.ERROR_CODE,"该账号已被锁定");
            }
            if (StringUtils.isEmpty(username)||StringUtils.isEmpty(password)) {
                throw new CustomException(StatusCode.ERROR_CODE, "用户名和密码不能为空!");
            }
            User  u = getByUsername(username);
            if (u == null) {
                throw new CustomException(StatusCode.ERROR_CODE, "用户名不存在!");
            }
            if(!MD5Util.checkpassword(password, u.getPassword())) {
                //新增登录失败记录
                addFailNum(session, username);
                throw new CustomException(StatusCode.ERROR_CODE, "用户名或密码错误!");
            }
          //清空登录失败记录
            cleanFailNum(session, username);
     
        
    }
    /**
         * 校验用户登录失败次数
         * @param session
         * @param username
         * @return
         */
        public boolean checkLock(HttpSession session,String username) {
            Object o = session.getServletContext().getAttribute(username);
            if(o==null) {
                return true;
            }
            HashMap<String,Object> map  = (HashMap<String, Object>) o;
            int num  = (int) map.get("num");
            Date date = (Date) map.get("lastDate");
            long timeDifference = ((new Date().getTime()-date.getTime())/60/1000);
            if(num>=3&&timeDifference<30) {
                return false;
            }
            return true;
        }
        /**
         * 新增用户登录失败次数
         * @param session
         * @param username
         */
        public void addFailNum(HttpSession session, String username) {
            Object o = session.getServletContext().getAttribute(username);
            HashMap<String,Object> map = null;
            int num= 0;
            if(o==null) {
                map = new HashMap<String,Object>();
            }else {
                map  = (HashMap<String, Object>) o;
                 num  = (int) map.get("num");
                 Date date = (Date) map.get("lastDate");
                 long timeDifference = ((new Date().getTime()-date.getTime())/60/1000);
                 if(timeDifference>=30) {
                     num=0;
                 }
            }
            map.put("num", num+1);
            map.put("lastDate", new Date());
            session.getServletContext().setAttribute(username, map);
        }
        /**
         * 清理用户登录失败的记录
         * @param session
         * @param username
         */
        public void cleanFailNum(HttpSession session, String username) {
            session.getServletContext().removeAttribute(username);
        }

    二、map

    /**
         * 移出非安全登录记录
         * 
         * @param index_
         */
        private void removeJPTLoginSecurity(String ip, String loginKey) {
            // 移出非安全记录索引
            nonSecurityIndex.remove(ip);
            nonSecurityIndex.remove(loginKey);
        }
    
        /**
         * 如果超出非安全登录记录的保存范围,则自动删除以往数据,非安全记录范围个数为30个
         */
        private void outJPTLoginSecurity() {
            if (null != nonSecurityIndex && nonSecurityIndex.keySet().size() > 30) {
                nonSecurityIndex.clear();
            }
        }
    
        private JPTLoginSecurity getSecurity(String ip, String loginKey) {
            JPTLoginSecurity security = null;
            if (null == nonSecurityIndex){
                return null;
            }
            security = nonSecurityIndex.get(ip);
            if (null == security){
                security = nonSecurityIndex.get(loginKey);
            }
            return security;
        }
    
        /**
         * 获取登录账户是否被锁定
         * 
         * @param index_
         * @return
         * @throws Exception
         */
        private boolean isLocked(String ip, String loginKey) throws Exception {
    
            JPTLoginSecurity security = getSecurity(ip, loginKey);
            if (null == security){
                return false;
            }
            Calendar c = Calendar.getInstance();
            Calendar now = Calendar.getInstance();
            c.setTime(security.getLastLoginTime());
            if (0 < security.getLocked()) {// 当前账号被锁定
                if (c.before(now)) {// 超过锁定时间,可再次登录
                    security.setLocked(0);// 对账号进行解锁
                    security.setLoginCount(1);
                    security.setLastLoginTime(new Date());
                    return false;
                }
                return true;// 锁定用户未超过锁定时间,不可登录
            }
            return false;
    
        }
    
        /**
         * 验证用户是否安全,一次连续尝试只能尝试10次(默认5分钟为一次连续尝试) 如果用户在一次尝试中连续尝试了10次以上则帐户被锁
         * 
         * @param ip
         *            ip地址
         * @param loginKey
         *            用户登录方式
         * @param index_
         *            非安全记录索引
         * @return
         * @throws Exception
         */
        private boolean isSafe(String ip, String loginKey) throws Exception {
            // 思路:
            // 1.如果索引存在,则直接计算
            // 2.如果索引不存在,调用outJPTLoginSecurity()计算是否超出记录范围,如果未超出则根据ip和loginKey生成非安全记录
            outJPTLoginSecurity();
            JPTLoginSecurity security = null;
            if (null == nonSecurityIndex) {
                //nonSecurityIndex = new HashMap<String, JPTLoginSecurity>();
                nonSecurityIndex = new ConcurrentHashMap<String, JPTLoginSecurity>();
            } else {
                security = getSecurity(ip, loginKey);
            }
            // TODO 判断用户是否安全
            if (null == security) {
                security = new JPTLoginSecurity();
                security.setLoginKey(loginKey);
                nonSecurityIndex.put(ip, security);
                nonSecurityIndex.put(loginKey, security);
            }
            Calendar c = Calendar.getInstance();
            Calendar now = Calendar.getInstance();
            c.setTime(security.getLastLoginTime());
    
            c.add(Calendar.MINUTE, 5);
            if (c.after(now)) {
                // 说明当前是连续登录
                if (security.getLoginCount() < 10) {
                    security.setLoginCount(security.getLoginCount() + 1);
                    return true;
                } else {
                    security.setLocked(1);
                    c = Calendar.getInstance();
                    c.setTime(new Date());
                    c.add(Calendar.MINUTE, 10);
                    security.setLastLoginTime(c.getTime());
                    return false;
                }
            } else {
                security.setLoginCount(1);
                security.setLastLoginTime(new Date());
                return true;
            }
        }
    private static Map<String, JPTLoginSecurity> nonSecurityIndex = null;
    public class JPTLoginSecurity implements Serializable{
    
        private String ip; // IP地址
        private String loginKey; //登录人账号或dn
        private int locked=0; //是否锁,0为未锁,1为锁
        private Date lastLoginTime=new Date(); //最后登录时间
        private int loginCount=0; //登录次数,10次为上限
        public JPTLoginSecurity() {
            super();
        }
        public String getIp() {
            return ip;
        }
        public void setIp(String ip) {
            this.ip = ip;
        }
        
        public String getLoginKey() {
            return loginKey;
        }
        public void setLoginKey(String loginKey) {
            this.loginKey = loginKey;
        }
        public int getLocked() {
            return locked;
        }
        public void setLocked(int locked) {
            this.locked = locked;
        }
        
        
        public Date getLastLoginTime() {
            return lastLoginTime;
        }
        public void setLastLoginTime(Date lastLoginTime) {
            this.lastLoginTime = lastLoginTime;
        }
        public int getLoginCount() {
            return loginCount;
        }
        public void setLoginCount(int loginCount) {
            this.loginCount = loginCount;
        }
        
        
    }
    if (nonSecurityIndex!=null&&isLocked(ip, loginKey)){
                //账户被锁定
                result = "-9";
                //return SUCCESS;
            }
    if (!isSafe(ip, loginKey)) {
                    result = "-9";
                    //增加用户登录失败次数控制 五分钟内用户只能连续尝试登录10次,超过账号将锁定10分钟
                    //return SUCCESS;
                } 
    // 登陆成功后如果存在非安全登录信息,则登录成功移除
                if (null != nonSecurityIndex){
                    removeJPTLoginSecurity(ip, loginKey);
                }
  • 相关阅读:
    整数安全
    Apache HTTP Server 处理连接的方式不能扩展,无法满足互联网不断发展的需求
    UNIX password system
    ws 应用场景
    事件驱动架构在 vivo 内容平台的实践 https://mp.weixin.qq.com/s/DpaSVMXSNomXsXb0dma0CA
    dmesg
    GraphQL及元数据驱动架构在后端BFF中的实践
    指向字符串的指针
    登录加密算法破解秘籍
    内存键值对存储
  • 原文地址:https://www.cnblogs.com/jentary/p/12174784.html
Copyright © 2020-2023  润新知