摘要:主要通过sql(oracle)实现连续X次输错密码后,禁止登录。Y小时或隔天后可以登录。

在javaweb项目的登录模块中经常会有连续X次输错密码后禁止登录的需求。这个功能可以通过多种方法来实现。本文只介绍以sql为主的方法,以供参考。

这是从实际项目中扒出来的代码,对一些变量名进行了处理,但是文中将包含全部核心代码。使用框架为struts2,ibatis。

需求:连续输入错误密码5次后,账号进入锁定状态,不可登录。锁定状态将于1小时后,或者下一个自然日(0点)解除。

具体方法描述。

1.建一张表来记录用户id,错误登录次数,上次登录时间。(也可以在user表上添加这三个字段,这样会省去一个初始化的麻烦)
2.登录失败后,进行校验:若已经错误登录5次,返回特定编码以告知前台显示错误信息。若次数不足5次,错误登录次数+1,并返回正常错误信息。若距离上一次错误登录时间已经过了1小时或者到了第二天,错误次数置为1。
3.若密码正确,并可以正常登录,将错误次数置为0。若处于锁定中,返回指定错误信息。

代码

建表语句

create table log_pwd_err(login_id number primary key, err_num number default 0, last_date date default sysdate);

java代码

    //参数的设置private static int maxTime = 5; //连续5次后private static double hour = 1; //一小时内不可登录。/*** 登录错误5次,一小时后不可登录* @param loginId 登录id* @param password 密码* @param isJiaMi 对密码进行加密处理* @return* @throws DataAccessException*/public Map<String, Object> validateByLoginIdLoginErr(String loginId, String password,boolean isJiaMi) throws DataAccessException {Map<String, Object> resultMap = new HashMap(2);User user = getByLoginId(loginId);    //一个通过登录id获取用户实体类的方法,文中无源码String encodePass = "";if (isJiaMi && null != isJiaMi) {encodePass = encrypt.encode(password);  //对密码进行加密处理,文中无源码}if(null != user){    //如果登录id确实存在if(user.getPassword().equals(encodePass)){ //并且密码输入正确if(this.checkWhenPwdOk(user)){    //校验该用户是否可以登录this.setErrZero(user);    //如果可以确实的登录,则对表中错误登录次数置零resultMap.put("user", user);return resultMap;}else {resultMap.put("extMsg", "errMax");    //前台错误信息展现由上层代码实现。return resultMap;}   }else {if(this.checkErrNum(user)){  //密码错误时的一系列操作//返回true时,错误次数超过了5次,需要返回特定的错误信息resultMap.put("extMsg", "errMax");return resultMap;}else {//错误次数没有超过5次,返回一个空map,交由上层处理return resultMap;}}}return resultMap;}private void setErrZero(User user){//将指定id的错误次数置零//client是操作数据库的方法,可以认为是SqlMapClientBuilder.buildSqlMapClient(Resources.getResourceAsReader("config/SqlMap.xml"));  这种东西。this.client.update("login.err.updateForOk", user);}/*** 即使密码正确,也不能登录* @param user* @return false 处于锁定中,无法登陆  true 可以正常登录*/private boolean checkWhenPwdOk(User user){Map<String, String> daoMap = new HashMap();daoMap.put("loginId", user.getLoginId() + "");daoMap.put("maxTime", maxTime + "");daoMap.put("hour", hour + "");String currentNumStr = (String) this.client.queryForObject("login.err.checkWhenPwdOk", daoMap);if(currentNumStr == null || currentNumStr.length() == 0){return true;    //err表中无数据,可以登录成功}if(Integer.valueOf(currentNumStr) >= maxTime){    //超过5次return false;}else {return true;}}//密码错误时的方法private boolean checkErrNum(User user){Map<String, String> daoMap = new HashMap();daoMap.put("loginId", user.getLoginId() + "");daoMap.put("maxTime", maxTime + "");daoMap.put("hour", hour + "");String currentNumStr = (String) this.client.queryForObject("login.err.getCurrentNum", daoMap);if(currentNumStr == null || currentNumStr.length() == 0){//错误信息表与用户表并不是同步的,如果是新建的用户,err表中将没有对应数据,需要插入一条新数据this.client.insert("login.err.insertUser", daoMap);currentNumStr = "0";}int currentNum = Integer.valueOf(currentNumStr);if(currentNum >= maxTime){//若次数超过了,将不会修改登陆时间。那样做会导致一小时的校验错误return true;}//执行+1或=1的操作this.client.update("login.err.updateForErr", daoMap);return false;}

sql文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd"><sqlMap namespace="login.err"><select id="getCurrentNum" resultClass="java.lang.String">
select decode(trunc(t1.last_date), trunc(sysdate), case when (sysdate - t1.last_date) * 24 > to_number(#hour#) and t1.err_num >= to_number(#maxTime#)then 1 <!-- 如果达到5次并且又过了1小时,原则上应该返回1 -->else t1.err_num end, 1) "flag" <!-- 过了一天还错也返回1 -->from log_pwd_err t1where t1.login_id = to_number(#loginId#)</select><insert id="insertUser">insert into log_pwd_err(login_id, err_num, last_date) values (#userId#, 1, sysdate)</insert><update id="updateForOk">update log_pwd_err t1set t1.err_num = 0,t1.last_date = sysdatewhere t1.login_id = to_number(#loginId#)and t1.err_num != 0</update><update id="updateForErr">update log_pwd_err t1set t1.err_num = decode(trunc(t1.last_date), trunc(sysdate), case when (sysdate - t1.last_date) * 24 > to_number(#hour#) and t1.err_num >= to_number(#maxTime#)then 1else t1.err_num + 1 end, 1),t1.last_date = sysdatewhere t1.login_id = to_number(#loginId#)</update><select id="checkWhenPwdOk" resultClass="java.lang.String">select casewhen trunc(t1.last_date) != trunc(sysdate) then0when to_number(#hour#) / 24 > sysdate - t1.last_date and t1.err_num >= to_number(#maxTime#) thent1.err_numelse0end "flag"from log_pwd_err t1where t1.login_id = to_number(#loginId#)</select></sqlMap>

总结:使用sql去完成这种需求最大的好处是逻辑清晰,集中,安全,并且不会出现bug。整个功能连写带测试加部署只花了2小时,比写这篇文章都短……缺点就是会对数据库造成一点点额外的压力。

javaweb项目实现连续3次输错密码后禁止登录相关推荐

  1. W7正在锁定计算机,win7输错密码锁定了怎么办 win7电脑被锁定的解锁方法

    虽然现在win10系统是最新的操作系统,还是有很多的win7系统继续使用,很多用户都会在电脑上设置密码,如果输错密码3次电脑则会被锁定一段时间,但是急用怎么办?大家可以看看下面的win系统输错密码被锁 ...

  2. 计算机密码锁定了怎么重装,Win7开机限制输错密码次数锁定计算机的设置方法...

    有些Win7系统用户可能忘记了开机密码,重复了好几次都没成功:不过,用户担心的是这种情况:开机输错几次依然还是可以继续"无限制输错",导致被盗可能性大大提高.那么,在Win7系统中 ...

  3. iphone已停用怎么解锁_iPhone多次输错密码已停用,连接iTunes,怎么办?

    两年前买了一部iphone8,因为当时用惯了安卓系统,不适应苹果的系统,用了一周,不习惯,搁置在抽屉里了,只是偶尔拿出来充充电. 最近,因为安卓手机内存快满了,手机很卡,想着把之前的苹果手机找出来用, ...

  4. .net mvc 输错密码锁定用户_国家工信部:手机有个密码必须设,否则钱包危险……...

    近期,一篇标题为<一部手机失窃而揭露的窃取个人信息实现资金盗取的黑色产业链>的文章引发关注和热议. 文中,不法分子偷盗个人手机后,在某政务APP窃取用户个人信息,进而申请网贷消费造成用户财 ...

  5. javaweb项目启动时日志不报错项目又起不来-跑空猫

    解决办法!!!!! 原因:tomcat 默认从WebContent下读文件   项目里没有WebContent这个文件夹 ,需要改成Webapp文件夹下的 配置:选中项目右键propties-搜索De ...

  6. CodeSmith输错license后的解决办法

    这几天重装了系统,原来的利器CodeSmith也需要再装..... 结果一着急把license输成standard版了 结果冒出提示一定需要Professional 的license faint! u ...

  7. mongodb输错命令后不能删除问题

    在用crt连接Linux操作MongoDB时,命令输错了,想删除的时候,却删除不了,原因是crt的配置有问题,解决办法如下 第一步:选项-->会话选项 转载于:https://www.cnblo ...

  8. 在git提交时输错密码,怎么办?

    在使用git提交代码的时候,失误将账号密码填写错误,导致提交失败,却又不知道该怎么办? $ git push origin master remote: Incorrect username or p ...

  9. git clone远程仓库时,输错密码如何解决?

    https://blog.csdn.net/github_38851471/article/details/84065698

  10. Mysql输错命令后如何退出

最新文章

  1. C#访问远程主机资源的方法
  2. 报名丨图神经网络前沿学术研讨会:清北高校vs企业,9位学者联袂分享
  3. 一根数据线玩转树莓派Zero
  4. thinkphp3.2 验证码生成和点击刷新验证码
  5. boost::log::dynamic_type_dispatcher用法的测试程序
  6. VTK:一个面向对象的可视化类库(zz)
  7. 机器学习的练功方式(十)——岭回归
  8. Gprinter Android SDK V2.1.4 使用说明
  9. 动态规划_leetcode322
  10. C---队列,栈的实现
  11. 手机怎么打开html游戏,网页游戏打不开怎么解决 网页游戏打不开解决方法
  12. Windows10必装的宝藏便签软件不用起来太可惜了
  13. 专访徐小平:AI已进入日常生活 没有泡沫只有彩虹
  14. 利用python代码 之将指定网易云歌单保存到Excel中
  15. 武汉科技大学计算机学院温文,第五届华中地区计算机类院校学生领袖峰会成功举行...
  16. 计算机专业大专考试题,计算机大专考试试题1.doc
  17. 9年前,字节跳动第一个安卓工程师是这样工作的
  18. 平面设计中的网格系统pdf_【200421】平面设计必看书籍超越平凡的设计平面设计中的网格系统等|电子书资源免费分享...
  19. 算法岗实习面经-字节跳动 PayPal 寒武纪 OPPO 平安科技等
  20. 苹果wifi网速慢怎么办_WiFi用着用着就断了?这样设置WiFi永不断网,大部分人不知道...

热门文章

  1. 不会吧,你还以为微信分账能解决“二清”?
  2. 项目管理知识体系指南(五)项目时间管理
  3. 咸鱼购买小米红米有锁机-完美解锁机有什么区别?MIUI解锁机升级系统
  4. 将洛奇的MML乐谱转为beep(蜂鸣器)乐谱
  5. 利用持续同调在基于深度学习的分割框架中引入显式的拓扑学约束
  6. android 中角度计算
  7. 十进制数转8421BCD码
  8. android 表情工厂,表情工厂安卓版
  9. ssm毕设项目小型超市货物仓储管理系统w8wry(java+VUE+Mybatis+Maven+Mysql+sprnig)
  10. 如何申请注册在国内可以登录使用国外邮箱?