登陆失败账号锁定

一、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);
            }
原文地址:https://www.cnblogs.com/jentary/p/12174784.html