平台登录时,1分钟内连续错误5次建议锁定帐号5分钟。

Posted lchzlp

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了平台登录时,1分钟内连续错误5次建议锁定帐号5分钟。相关的知识,希望对你有一定的参考价值。

登录controller

package com.zx.znydweb.controller;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.zx.znyd.common.LoginLock;
import com.zx.znyd.common.SpringContextUtil;
import com.zx.znyd.dao.UserDao;
import com.zx.znyd.data.model.User;
import com.zx.znydweb.interceptor.CheckLoggin;

@Controller
public class LoginController {
    private static final Logger logger = LoggerFactory.getLogger(LoginController.class);
    public static final String LOGINUSER = "LOGINUSER";
    public static final String ERRORMsg = "LoginController_ERRORMsg";
    public static final String USERNAME = "userName";
    public static final String PASSWORD = "passWord";

    @Autowired
    LoginLock redisUtil;
    
    @ResponseBody
    @RequestMapping(value = "/", method = RequestMethod.POST)
    public Map<String, Object> login(String userName, String passWord, String piccode, HttpSession session,
            HttpServletRequest req) {
    	//经过滤器过滤后重新赋值
    	passWord = req.getParameter("passWord");
    	piccode = req.getParameter("piccode");
    	userName = req.getParameter("userName");
        logger.trace("=======login====,{},{},{}", userName, passWord, piccode);
        Map<String, Object> retMap = new HashMap<String, Object>();
        // 判断该用户是否被锁
        boolean isLock = redisUtil.isLoginLock(userName);
        if(isLock) {
        	logger.info("用户"+userName+"被锁定,请在5分钟之后重试:"+isLock);
        	retMap.put("returnCode", "999");
            retMap.put("returnMessage", "用户"+userName+"被锁定,请在5分钟之后重试");
            return retMap;
        } 
        if (session.getAttribute(LOGINUSER) == null) {
            String sessionPicCode = (String) session.getAttribute(VerifyCodeController.verifyCode);
            if (!checkLogInData(userName, passWord, piccode, retMap)) {
                session.setAttribute(ERRORMsg, retMap.get("returnMessage"));
                session.setAttribute(USERNAME, userName);
                session.setAttribute(PASSWORD, passWord);
            } else if (!(sessionPicCode != null && sessionPicCode.equalsIgnoreCase(piccode))) {
                session.setAttribute(ERRORMsg, "验证码错误");
                session.setAttribute(USERNAME, userName);
                session.setAttribute(PASSWORD, passWord);
            } else {
                UserDao userDao = SpringContextUtil.getBean(UserDao.class);
                try {
                    User u = userDao.findOneByUsernameAndPass(userName, passWord);
                    if (u != null) {
                        if (UserDao.validstatus.equals(u.getStatus())) {
                            session.setAttribute(LOGINUSER, u);

                            session.setAttribute(ERRORMsg, "");
                            logger.info("User [{}] loggin success.", u.getUserName());
                        } else {
                            session.setAttribute(ERRORMsg, "用户状态已失效");
                            session.setAttribute(USERNAME, userName);
                        }

                    } else {
                        session.setAttribute(ERRORMsg, "用户名或密码错误");
                        session.setAttribute(USERNAME, userName);
                    }
                } catch (Exception e) {
                    session.setAttribute(ERRORMsg, "用户名或密码错误");
                    session.setAttribute(USERNAME, userName);
                }
            }
        }

        if (session.getAttribute(LOGINUSER) != null) {
        	// 某时间间隔内用户输入错误次数
        	Long retriesLockNum = redisUtil.getLoginRetriesLockNum(userName);
            if(retriesLockNum != null && retriesLockNum < 5 && retriesLockNum > 0) {
            	logger.info("登录成功,删除用户"+userName+"重试失败次数:"+retriesLockNum);
            	redisUtil.delLoginRetriesLock(userName);
            } else if(retriesLockNum >= 5){// 处理并发
            	logger.info("用户"+userName+"重试失败次数:"+retriesLockNum);
            	 isLock = redisUtil.isLoginLock(userName);
            	 logger.info("用户"+userName+"被锁定,请在5分钟之后重试:"+isLock);
                 if(!isLock) {
                	 redisUtil.loginLock(userName, 60*5);
                 } 
                 retMap.put("returnCode", "999");
                 retMap.put("returnMessage", "用户"+userName+"被锁定,请在5分钟之后重试");
                 return retMap;
            }
            // 用户已登陆
            retMap.put("returnCode", "0");
            retMap.put("returnMessage", "登陆成功");
            return retMap;
        }
        
        // 某时间间隔内用户输入错误次数
        Long retriesLockNum = redisUtil.setloginRetriesLockNum(userName, 60);
        logger.info("用户"+userName+"重试失败次数:"+retriesLockNum);
        if(retriesLockNum != null && retriesLockNum >= 5) {
        	isLock = redisUtil.loginLock(userName, 60*5);
        	logger.info("用户"+userName+"被锁定,请在5分钟之后重试:"+isLock);
        }
        if (!StringUtils.isEmpty((String) session.getAttribute(ERRORMsg))) {
            req.setAttribute("errorMsg", (String) session.getAttribute(ERRORMsg));
            req.setAttribute("userName", (String) session.getAttribute(USERNAME));
            req.setAttribute("passWord", (String) session.getAttribute(PASSWORD));
        } else {
            req.setAttribute("errorMsg", "");
            req.setAttribute("userName", "");
            req.setAttribute("passWord", "");
        }
        retMap.put("returnCode", "999");
        retMap.put("returnMessage", session.getAttribute(ERRORMsg).toString());
        return retMap;
    }

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String login(HttpSession session, HttpServletRequest req) {

        if (session.getAttribute(LOGINUSER) != null) {
            // 用户已登陆
            return "main";
        }
        if (!StringUtils.isEmpty((String) session.getAttribute(ERRORMsg))) {
            req.setAttribute("errorMsg", (String) session.getAttribute(ERRORMsg));
            req.setAttribute("userName", (String) session.getAttribute(USERNAME));
            req.setAttribute("passWord", (String) session.getAttribute(PASSWORD));
        } else {
            req.setAttribute("errorMsg", "");
            req.setAttribute("userName", "");
            req.setAttribute("passWord", "");
        }
        session.setAttribute(ERRORMsg, "");
        return "index";
    }

    @CheckLoggin
    @RequestMapping(value = "/userLogout", method = RequestMethod.POST)
    @ResponseBody
    public Map userLogout(HttpSession session) {
        session.invalidate();
        Map reture = new HashMap();
        reture.put("returnCode", "0");
        reture.put("returnMessage", "成功");
        return reture;
    }

    /**
     * For 4A 单点登录
     * 
     * @param userName
     * @param passWord
     * @param piccode
     * @param session
     * @param req
     * @return
     */
    @RequestMapping(value = "/SSOLogin")
    public String sSOLogin(HttpSession session, HttpServletRequest req) {
        Cookie[] cookies = req.getCookies();
        if (cookies != null) for (Cookie cookie : cookies) {
            if (cookie.getName().equals("info_inside")) {
                String[] valArray;
                try {
                    valArray = new String(Base64.decodeBase64(cookie.getValue())).split("\\|");
                    if (valArray.length != 4) {
                        session.setAttribute(ERRORMsg, "获取统一登录平台参数错误!");
                    } else if (!valArray[2].equals(getTokenStr(valArray[0] + valArray[1]))) {
                        session.setAttribute(ERRORMsg, "未知来源请求!");
                    } else if (System.currentTimeMillis() - Long.parseLong(valArray[3]) > 3600 * 1000) {
                        session.setAttribute(ERRORMsg, "请求已超时,请重新登录!");
                    } else {
                        logger.trace("=======login====,{},{},{}", valArray[0], valArray[1], valArray[2], valArray[3]);
                        if (session.getAttribute(LOGINUSER) == null) {
                            UserDao userDao = SpringContextUtil.getBean(UserDao.class);
                            try {
                                User u = userDao.findOneByUsername(valArray[0]);
                                if (u != null) {
                                    if (UserDao.validstatus.equals(u.getStatus())) {
                                        session.setAttribute(LOGINUSER, u);
                                        session.setAttribute(ERRORMsg, "");
                                        logger.info("User [{}] SSOLogin success.", u.getUserName());
                                    } else {
                                        session.setAttribute(ERRORMsg, "用户状态已失效");
                                    }
                                } else {
                                    session.setAttribute(ERRORMsg, "用户名或密码错误");
                                }
                            } catch (Exception e) {
                                session.setAttribute(ERRORMsg, "用户名或密码错误");
                            }
                        }
                    }
                } catch (Exception e1) {
                    logger.trace("=======获取统一登录平台参数错误!====,{}", cookie.getValue());
                }
                break;
            }
        }
        return "redirect:/";
    }

    /**
     * 加密算法
     * 
     * @param i1
     * @return
     */
    private String getTokenStr(String i1) {
        String i2 = "";
        for (int i = 0; i < i1.length(); i++) {
            int c = (int) i1.charAt(i);
            if (c >= 48 && c <= 57) {
                c = c - 48;
                c = (c + 5) % 10;
                c = c + 48;
            } else if (c >= 97 && c <= 122) {
                c = c - 97;
                c = (c + 13) % 26;
                c = c + 97;
            }
            i2 = i2 + (char) c;
        }
        return i2;
    }

    private boolean checkLogInData(String userName, String passWord, String piccode, Map<String, Object> retMap) {
        // 用户名校验
        String regex = "^[a-zA-Z0-9_\\-]+$";
        if (!userName.matches(regex)) {
            retMap.put("returnMessage", "用户名只能包含字母数字下划线或横杠");
            return false;
        }
        if (userName.length() > 20) {
            retMap.put("returnMessage", "用户名长度不能大于20位");
            return false;
        }
        //密码校验
        if (!passWord.matches(regex)) {
            retMap.put("returnMessage", "用户名或密码错误");
            return false;
        }
        if (passWord.length() > 20) {
            retMap.put("returnMessage", "密码长度不能大于20位");
            return false;
        }
        if (passWord.length() < 6) {
            retMap.put("returnMessage", "密码长度不能小于6位");
            return false;
        }
        // 验证码校验
        String regex2 = "^[a-zA-Z0-9]+$";
        if (!piccode.matches(regex2)) {
            retMap.put("returnMessage", "验证码只能包含字母或数字");
            return false;
        }
        if (piccode.length() != 4) {
            retMap.put("returnMessage", "验证码长度必须是4位");
            return false;
        }
        retMap.put("returnMessage", "");
        return true;

    }

}

 工具类

package com.zx.znyd.common;

import java.io.Serializable;
import java.util.Date;
import java.util.Map;

import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import redis.clients.jedis.Jedis;

import com.cmos.core.logger.util.StringUtils;


/**
 * @Description: 登录锁定(*分钟失败*次,锁定*分钟)
 * @author 弓振
 * @date 2018年2月26日
 */
@Component
public class LoginLock {
	@Autowired
	@Qualifier("redisTemplate1")
	private RedisTemplate<Serializable, Object> redisTemplate1;
	/**
	 * 登录次数验证
	 * @param key
	 * @param retriesLifecycleTime 多长时间内重试有效(秒)
	 */
	public Long setloginRetriesLockNum(String key, int retriesLifecycleTime) {
		 String retriesLockscript = "local errorNum = redis.call(‘get‘,KEYS[1]) "
		 		+ "if errorNum == false "
		 			+ "then errorNum = redis.call(‘incr‘,KEYS[1]) redis.call(‘expire‘,KEYS[1],tonumber(ARGV[1])) return errorNum "
		 		+ "else return redis.call(‘incr‘,KEYS[1]) end";
		Long retriesLockNum = executeScript(retriesLockscript, 1, key, String.valueOf(retriesLifecycleTime));
		return retriesLockNum;
	}
	
	/**
	 * 登录次数多,锁定
	 * @param key
	 * @param retriesLifecycleTime 多长时间内重试有效(秒)
	 * @param retriesNum 重试次数
	 * @param lockTime 锁定时间(秒)
	 * @return 锁定true,否则false
	 */
	public boolean loginLock(String key,int lockTime) {
		String lockKey = key+"_lock";
		String lockScript = "if redis.call(‘setnx‘,KEYS[1],ARGV[1]) == 1 "
				+ "then redis.call(‘expire‘,KEYS[1],tonumber(ARGV[2])) return 1 "
				+ "else return 2 end";
		String nowTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:dd:ss");
		Long isLocked = executeScript(lockScript, 1, lockKey, nowTime, String.valueOf(lockTime));
		return isLocked != null && isLocked==1 ? true : false;		
	}
	
	/**
	 * 删除重置lock
	 * @param key 
	 * @return
	 */
	public boolean delLoginRetriesLock(String key) {
		if(redisTemplate1.hasKey(key)) {
			redisTemplate1.delete(key);
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * 得到失败次数
	 * @param key
	 * @return
	 */
	public Long getLoginRetriesLockNum(String key) {
		String retriesLockscript = "return redis.call(‘get‘,KEYS[1]) ";
		String errorNum = executeScript(retriesLockscript, 1, key);
		return StringUtils.isBlank(errorNum) ? 0L : Long.parseLong(errorNum);
	}
	
	/**
	 * 是否锁定
	 * @param key
	 * @return 锁定 true,否则false
	 */
	public boolean isLoginLock(String key) {
		String lockKey = key+"_lock";
		String lockScript = "return redis.call(‘get‘,KEYS[1]) ";
		String lockVlaue = executeScript(lockScript, 1, lockKey);
		return StringUtils.isBlank(lockVlaue) ? false : true;
	}
	
	private <T> T executeScript(final String script, final int keyCount, final String... values) {
		T value = redisTemplate1.execute(new RedisCallback<T>(){
			@SuppressWarnings("unchecked")
			@Override
			public T doInRedis(RedisConnection connection)
					throws DataAccessException {
				Jedis jedis = (Jedis) connection.getNativeConnection();
				return (T) jedis.eval(script, keyCount, values);
			}
		});
		return value;
	}
}

  

以上是关于平台登录时,1分钟内连续错误5次建议锁定帐号5分钟。的主要内容,如果未能解决你的问题,请参考以下文章

django实现登录时候输入密码错误5次锁定用户十分钟

django 实现登录时候输入密码错误5次锁定用户十分钟

设置帐户锁定策略 若用户连续有3次无效登陆则该帐户自动锁定20分钟 怎么弄

asp.net 30分钟内5次登陆错误,锁定账号。

引用的帐号当前已锁定,且可能无法登录,win7的电脑,怎么解开?

解决帝国cms系统后台管理员登录密码输入五次密码错误后需等候60分钟的方法