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.