Implementation of daily login failure limit based on Redis

  • 2020-06-23 02:15:54
  • OfStack

1. The train of thought

Here is the code I wrote before, without considering high concurrency scenarios. In high concurrency scenario, incr can be used instead of get to consider the coverage value of set method. set ensures data security

Record the number of login failures via redis, with username for the user as key

Every time we receive a login request, we will go to redis to check whether the login number is greater than or equal to the limit number we set. If yes, we will return it directly

Code 2.

Foreground login and background query database code ellipsis

2.1 controller

I'm using Jboot here, and the way to get redisTemplate is Jboot.me().getRedis() spring, jedisTemplate.


//  If the user enters the password to log in more than the limit ,24 Hours no login 
 //  Set up the 1 Limit the number of failures per day , The default is 10 time 
 final int limit = 3;
 JbootRedis jr = Jboot.me().getRedis();
 //Constants.LOGIN_COUNT = "LOGIN_COUNT"
 //account It's the page username
 String key = Constants.LOGIN_COUNT + "_" + account;
 Integer count = jr.get(key);
 if(count == null){
   count = 0;
 }else {
   if (count >= limit) {
     // Direct return 
     ajaxJson.setMsg(" You have exceeded the limit for logins today, please try again tomorrow. ");
     ajaxJson.setSuccess(false);
     logger.error(" Account for the "+account+" ] users logged in more than the maximum number of times in one day ");
     render(callback, gson.toJson(ajaxJson));
     return;
   }
 }
//...  Go to the database username The query user object 
 if (user != null) {
   //  to redis Increases the number of login failures 
   Integer newCount = IncrFailLoginCount(key,count);
   logger.error(" Account for the "+account+" User login failed ,"+ajaxJson.getMsg());
   ajaxJson.setMsg(ajaxJson.getMsg() + " , the remaining login frequency is: "+(limit-newCount));
   render(callback, gson.toJson(ajaxJson));
   return;
 }else{
   //  Login successful , remove redis Failure to record 
   jr.del(key);
 }

2.2 IncrFailLoginCount method


/**
 * 1 Statistics on the number of login failures in a day 
 * @param key redis The key stored in 
 * @param count  Number of logins that have failed 
 * @return count  Logon failure times 
 */
private Integer IncrFailLoginCount(String key,Integer count) {
  JbootRedis jr = Jboot.me().getRedis();
  count++;
  // Set the expiration time to tonight 23 point 59 points 59 seconds 
  long timeInMillis = DateUtils.getMillsecBeforeMoment(23, 59, 59, 999);
  if (timeInMillis < 100){
    //  Avoid at the end 1 Logins in seconds cause the expiration time to be too small or even negative 
    timeInMillis = 1000*60;
  }
  //  Set expiration time 
  jr.set(key,count);
  // Notice the order here ,  First, set again pexpire
  jr.pexpire(key,timeInMillis);
  return count;
}

1 utility class of time is used here, the specific code is as follows:


/**
*  Gets the number of milliseconds between the current time and the specified time 
* @param hour  The hour specified for the hour 
* @param min  Minutes to specify the time 
* @param sec  Seconds to specify the moment 
* @param mill  Specify the milliseconds of the time 
* @return
*/
public static long getMillsecBeforeMoment(int hour,int min,int sec,int mill){
  return getMillisecBetweenDate(new Date(),getMoment(hour,min,sec,mill));
}
/**
*  Gets the number of milliseconds between two dates 
 * @param before
 * @param after
 * @return
 */
public static long getMillisecBetweenDate(Date before, Date after){
 long beforeTime = before.getTime();
 long afterTime = after.getTime();
 return afterTime - beforeTime;
}
/**
*  Get something of the day 1 moment Date
 * @param hour 24 hours 
 * @param min  minutes 
 * @param sec  seconds 
 * @param mill  ms 
 * @return
 */
public static Date getMoment(int hour,int min,int sec,int mill){
 Calendar calendar = Calendar.getInstance();
 calendar.setTime(new Date());
 calendar.set(Calendar.HOUR_OF_DAY,hour);
 calendar.set(Calendar.MINUTE,min);
 calendar.set(Calendar.SECOND,sec);
 calendar.set(Calendar.MILLISECOND,mill);
 return calendar.getTime();
}

3. Summary

One thing to note here is that after redis sets the expiration time, re-set will clear the expiration effect and make it permanent again, so pexpire() needs to be used every time
redis there is one method: incr (), each call to this method, can make a key value + 1, if don't have the key, again will be the initial of 0 + 1. Suitable for making counter, also can be used to this case, but only when I am here just want to login failure count + 1, login before judging count directly, so using the traditional get (), set (). Interested students can go to understand in detail.


Related articles: