基于Redis实现每日登录失败次数限制

1. 思路

下面是我以前写的代码,没考虑高并发场景。如果是高并发场景下,要考虑到redis的set方法覆盖值问题,可以使用incr来替代get,set保证数据安全

通过redis记录登录失败的次数,以用户的username为key

每次收到登录的请求时,都去redis查询登录次数是否已经大于等于我们设置的限制次数, 是的话直接返回

2. 代码

前台登录和后台查询数据库的代码省略

2.1 controller

我这里使用的Jboot, 获取redisTemplate的方式是Jboot.me().getRedis(), spring的话用jedisTemplate就行.

// 如果用户输入账号密码有效登录超过限制次数,24小时禁止登录
 // 设置一天限制失败次数,默认为10次
 final int limit = 3;
 JbootRedis jr = Jboot.me().getRedis();
 //Constants.LOGIN_COUNT = "LOGIN_COUNT"
 //account是页面传过来的username
 String key = Constants.LOGIN_COUNT + "_" + account;
 Integer count = jr.get(key);
 if(count == null){
   count = 0;
 }else {
   if (count >= limit) {
     //直接返回
     ajaxJson.setMsg("您今天登录失败的次数已经超过限制,请明天再试。");
     ajaxJson.setSuccess(false);
     logger.error("账号为【"+account+"】的用户单日登录次数超过上限");
     render(callback, gson.toJson(ajaxJson));
     return;
   }
 }
//... 去数据库根据username查询user对象
 if (user != null) {
   // 往redis中增加登录失败的次数
   Integer newCount = IncrFailLoginCount(key,count);
   logger.error("账号为【"+account+"】的用户登录失败,"+ajaxJson.getMsg());
   ajaxJson.setMsg(ajaxJson.getMsg() + ",剩下登录次数为:"+(limit-newCount));
   render(callback, gson.toJson(ajaxJson));
   return;
 }else{
   // 登录成功,清除redis失败记录
   jr.del(key);
 }

2.2 IncrFailLoginCount方法

/**
 * 一天中登录失败的次数统计
 * @param key redis中存储的键
 * @param count 已经登录失败的次数
 * @return count 登录失败次数
 */
private Integer IncrFailLoginCount(String key,Integer count) {
  JbootRedis jr = Jboot.me().getRedis();
  count++;
  //设置过期时间为今晚23点59分59秒
  long timeInMillis = DateUtils.getMillsecBeforeMoment(23, 59, 59, 999);
  if (timeInMillis < 100){
    // 避免在最后一秒的时候登录导致过期时间过小甚至为负数
    timeInMillis = 1000*60;
  }
  // 设置过期时间
  jr.set(key,count);
  //这里注意顺序, 先set再pexpire
  jr.pexpire(key,timeInMillis);
  return count;
}

这里用到了时间的一个工具类, 具体代码如下:

/**
* 获取当前时间到指定时刻前的毫秒数
* @param hour 指定时刻的小时
* @param min 指定时刻的分钟
* @param sec 指定时刻的秒
* @param mill 指定时刻的毫秒
* @return
*/
public static long getMillsecBeforeMoment(int hour,int min,int sec,int mill){
  return getMillisecBetweenDate(new Date(),getMoment(hour,min,sec,mill));
}
/**
* 获取两个日期之间的毫秒数
 * @param before
 * @param after
 * @return
 */
public static long getMillisecBetweenDate(Date before, Date after){
 long beforeTime = before.getTime();
 long afterTime = after.getTime();
 return afterTime - beforeTime;
}
/**
* 获取当天的某一时刻Date
 * @param hour 24小时
 * @param min 分钟
 * @param sec 秒
 * @param mill 毫秒
 * @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. 总结

这里有个地方要注意,就是redis 设置过期时间后,重新set会清除过期效果, 重新变成永久状态, 所以需要每次都pexpire()
redis中还有一个方法:incr(),每次调用这个方法,都会让一个键的值+1,如果没有这个键,会初始为0再+1. 适合做计数器, 也能再这个案例中使用, 但是我这里只是希望登录失败的时候才计数+1 , 登录之前直接判断count, 所以使用了传统的get(),set(). 有兴趣的同学可以去详细了解.

(0)

相关推荐

  • php 使用redis锁限制并发访问类示例

    本文介绍了php 使用redis锁限制并发访问类,并详细的介绍了并发访问限制方法. 1.并发访问限制问题 对于一些需要限制同一个用户并发访问的场景,如果用户并发请求多次,而服务器处理没有加锁限制,用户则可以多次请求成功. 例如换领优惠券,如果用户同一时间并发提交换领码,在没有加锁限制的情况下,用户则可以使用同一个换领码同时兑换到多张优惠券. 伪代码如下: if A(可以换领)     B(执行换领)     C(更新为已换领) D(结束) 如果用户并发提交换领码,都能通过可以换领(A)的判断,因

  • PHP实现redis限制单ip、单用户的访问次数功能示例

    本文实例讲述了PHP实现redis限制单ip.单用户的访问次数功能.分享给大家供大家参考,具体如下: 有时候我们需要限制一个api或页面访问的频率,例如单ip或单用户一分钟之内只能访问多少次 类似于这样的需求很容易用Redis来实现 <?php $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $redis->auth("php001"); //这个key记录该ip的访问次数 也可改成用户id //$k

  • Redis实战记录之限制操作频率

    前言 最近沉迷于业务开发无法自拔

  • 在Redis数据库中实现分布式速率限制的方法

    问题 在许多应用中,对昂贵的资源的访问必须加以限制,此时速率限制是必不可少的.许多现代网络应用程序在多个进程和服务器上运行,状态需要被共享.一个理想的解决方案应该是高效. 快捷的,而不是依赖于被绑定到特定客户端的单个应用程序服务器(由于负载平衡) 或本身持有任何状态. 解决方案 实现这一目标的一个简单有效的方法就是使用 Redis, 它有很多有用的数据结构和功能, 尽管实现速率限制只需要2个功能用: 一.在某个具体的键值上递增一个整数,二.给这个键值设置过期时间. 因为redis 有个单一的事件

  • redis 实现登陆次数限制的思路详解

    title: redis-login-limitation  利用 redis 实现登陆次数限制, 注解 + aop, 核心代码很简单. 基本思路 比如希望达到的要求是这样: 在 1min 内登陆异常次数达到5次, 锁定该用户 1h 那么登陆请求的参数中, 会有一个参数唯一标识一个 user, 比如 邮箱/手机号/userName 用这个参数作为key存入redis, 对应的value为登陆错误的次数, string 类型, 并设置过期时间为 1min. 当获取到的 value == "4&qu

  • 基于Redis实现每日登录失败次数限制

    1. 思路 下面是我以前写的代码,没考虑高并发场景.如果是高并发场景下,要考虑到redis的set方法覆盖值问题,可以使用incr来替代get,set保证数据安全 通过redis记录登录失败的次数,以用户的username为key 每次收到登录的请求时,都去redis查询登录次数是否已经大于等于我们设置的限制次数, 是的话直接返回 2. 代码 前台登录和后台查询数据库的代码省略 2.1 controller 我这里使用的Jboot, 获取redisTemplate的方式是Jboot.me().g

  • Oracle用户连续登录失败次数限制如何取消

    当用户连续登录失败次数过多时,Oracle会锁定该用户,"FAILED_LOGIN_ATTEMPTS"用于设置最大次数,超过该值则锁定该帐号. 要取消用户连续登录失败次数的限制可以按照以下方法操作: 1. 输入以下命令,查看"FAILED_LOGIN_ATTEMPTS"的值: SQL> select * from dba_profiles s where s.profile='DEFAULT' and resource_name='FAILED_LOGIN_A

  • springboot整合shiro登录失败次数限制功能的实现代码

    这次讲讲如何限制用户登录尝试次数,防止坏人多次尝试,恶意暴力破解密码的情况出现,要限制用户登录尝试次数,必然要对用户名密码验证失败做记录,Shiro中用户名密码的验证交给了CredentialsMatcher 所以在CredentialsMatcher里面检查,记录登录次数是最简单的做法.当登录失败次数达到限制,修改数据库中的状态字段,并返回前台错误信息.  因为之前的博客都是用的明文,这里就不对密码进行加密了,如果有需要加密,将自定义密码比较器从SimpleCredentialsMatcher

  • Laravel登录失败次数限制的实现方法

    在用户身份验证的情况下,Laravel 具有内置的身份验证系统.我们可以根据要求轻松修改它.身份验证中包含的功能之一是Throttling. 为什么我们需要throttling保护? 基本上,throttling是用来保护暴力攻击的.它将在一定时间内检查登录尝试.在短登录中,throttling会计算用户或机器人尝试失败的登录尝试次数. 使用自定义登录实现限制 默认情况下,在内置身份验证控制器中实现限制.但是,如果我们需要实现它到自定义登录呢? 实现自定义登录限制非常容易.首先,我们必须将Thr

  • SpringBoot+Shiro学习之密码加密和登录失败次数限制示例

    这个项目写到现在,基本的雏形出来了,在此感谢一直关注的童鞋,送你们一句最近刚学习的一句鸡汤:念念不忘,必有回响.再贴一张ui图片: 前篇思考问题解决 前篇我们只是完成了同一账户的登录人数限制shiro拦截器的编写,对于手动踢出用户的功能只是说了采用在session域中添加一个key为kickout的布尔值,由之前编写的KickoutSessionControlFilter拦截器来判断是否将用户踢出,还没有说怎么获取当前在线用户的列表的核心代码,下面贴出来: /** * <p> * 服务实现类

  • Centos7下用户登录失败N次后锁定用户禁止登陆的方法

    前言 针对linux上的用户,如果用户连续3次登录失败,就锁定该用户,几分钟后该用户再自动解锁.Linux有一个pam_tally2.so的PAM模块,来限定用户的登录失败次数,如果次数达到设置的阈值,则锁定用户. PAM的配置文件介绍 PAM配置文件有两种写法: 一种是写在/etc/pam.conf文件中,但centos6之后的系统中,这个文件就没有了. 另一种写法是,将PAM配置文件放到/etc/pam.d/目录下,其规则内容都是不包含 service 部分的,即不包含服务名称,而/etc/

  • 基于redis实现token验证用户是否登陆

    基于项目需求, 我们要实现一个基于redis实现token登录验证,该如何实现呢: 后端实现: 1.引入redis相关的依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupI

  • Postgresql限制用户登录错误次数的实例代码

    在oracle中我们可以通过设置FAILED_LOGIN_ATTEMPTS来限制用户密码登录错误的次数,但是在postgresql中是不支持这个功能的.尽管PostgreSQL支持event trigger,可是event局限于DDL,对于登录登出事件是没办法使用event trigger的. 不过像登录新建会话触发某个事件这个需求可以通过hook实现,不过该方法比较复杂,需要修改内核代码,在客户端认证中添加逻辑,判断输入密码次数统计.这里推荐一种比较简单的方法实现类似的功能. 这里我们要使用到

  • PostgreSQL用户登录失败自动锁定的处理方案

    墨墨导读:PostgreSQL使用session_exec插件实现用户密码验证失败几次后自动锁定,本文介绍一种处理方案. 一.插件session_exec安装配置篇 下载插件并编译安装. https://github.com/okbob/session_exec $ unzip session_exec-master.zip $ cd session_exec-master/ $ make pg_config=/opt/pgsql/bin/pg_config $ make pg_config=/

  • 基于Redis实现短信验证码登录项目示例(附源码)

    目录 Redis短信登录流程描述 短信验证码的发送 短信验证码的验证 是否登录的验证 源码分析 模拟发送短信验证码 短信验证码的验证 校验是否登录 登录验证优化 Redis短信登录流程描述 短信验证码的发送 用户提交手机号,系统验证手机号是否有效,毕竟无效手机号会消耗你的短信验证次数还会导致系统的性能下降.如果手机号为无效的话就让用户重新提交手机号,如果有效就生成验证码并将该验证码作为value保存到redis中对应的key是手机号,之所以这么做的原因是保证key的唯一性,如果使用固定字符串作为

随机推荐