专栏名称: 芋道源码
纯 Java 源码分享公众号,目前有「Dubbo」「SpringCloud」「Java 并发」「RocketMQ」「Sharding-JDBC」「MyCAT」「Elastic-Job」「SkyWalking」「Spring」等等
目录
相关文章推荐
芋道源码  ·  高性能、无侵入的 Java 性能监控神器 ·  昨天  
Java编程精选  ·  手把手教你Java文件断点下载 ·  3 天前  
Java编程精选  ·  阿里员工吐槽:80%以上的leader认为, ... ·  4 天前  
芋道源码  ·  别乱分层,PO、VO、DAO、BO、DTO、 ... ·  2 天前  
51好读  ›  专栏  ›  芋道源码

三次输错密码后,系统是怎么做到不让我继续尝试的?

芋道源码  · 公众号  · Java  · 2025-05-16 09:30

正文

请到「今天看啥」查看全文


3 那么自己动手实现一下

前端部分

首先写一个账密输入页面,使用很简单HTML加表单提交




 登录页面
 
  body {
   background-color: #F5F5F5;
  }
  form {
   width: 300px;
   margin: 0 auto;
   margin-top: 100px;
   padding: 20px;
   background-color: white;
   border-radius: 5px;
   box-shadow: 0 0 10px rgba(0,0,0,0.2);
  }
  label {
   display: block;
   margin-bottom: 10px;
  }
  input[type="text"], input[type="password"] {
   border: none;
   padding: 10px;
   margin-bottom: 20px;
   border-radius: 5px;
   box-shadow: 0 0 5px rgba(0,0,0,0.1);
   width: 100%;
   box-sizing: border-box;
   font-size: 16px;
  }
  input[type="submit"] {
   background-color: #30B0F0;
   color: white;
   border: none;
   padding: 10px;
   border-radius: 5px;
   box-shadow: 0 0 5px rgba(0,0,0,0.1);
   width: 100%;
   font-size: 16px;
   cursor: pointer;
  }
  input[type="submit"]:hover {
   background-color: #1C90D6;
  }
 


 
"http://localhost:8080/login" method="get">
 
  "text" id="username" name="username" placeholder="请输入用户名" required>
 
  "password" id="password" name="password" placeholder="请输入密码" required>
  "submit" value="登录">
 


效果如下:

后端部分

技术选型分析

首先我们画一个流程图来分析一下这个登录限制流程

  • 从流程图上看,首先访问次数的统计与判断不是在登录逻辑执行后,而是执行前就加1了;
  • 其次登录逻辑的成功与失败并不会影响到次数的统计;
  • 最后还有一点流程图上没有体现出来,这个次数的统计是有过期时间的,当过期之后又可以重新登录了。

那为什么是Redis+Lua脚本呢?

Redis的选择不难看出,这个流程比较重要的是存在一个用来计数的变量,这个变量既要满足分布式读写需求,还要满足全局递增或递减的需求,那Redis的incr方法是最优选了。

那为什么需要Lua脚本呢?流程上在验证用户操作前有些操作,如图:

这里至少有3步Redis的操作,get、incr、expire,如果全放到应用里面来操作,有点慢且浪费资源。

Lua脚本的优点如下:

  • 减少网络开销。 可以将多个请求通过脚本的形式一次发送,减少网络时延。
  • 原子操作。 Redis会将整个脚本作为一个整体执行,中间不会被其他请求插入。因此在脚本运行过程中无需担心会出现竞态条件,无需使用事务。
  • 复用。 客户端发送的脚本会永久存在redis中,这样其他客户端可以复用这一脚本,而不需要使用代码完成相同的逻辑。

最后为了增加功能的复用性,我打算使用Java注解的方式实现这个功能。

代码实现

项目结构如下

配置文件

pom.xml

"1.0" encoding="UTF-8"?>
"http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4.0.0
   
        org.springframework.boot
        spring-boot-starter-parent
        2.7.11
       
   
    com.example
    LoginLimit
    0.0.1-SNAPSHOT
    LoginLimit
    Demo project for Spring Boot
   
        1.8
   
   
       
            org.springframework.boot
            spring-boot-starter-web
       

       
            org.springframework.boot
            spring-boot-starter-test
            test
       
       
       
            org.springframework.boot
            spring-boot-starter-data-redis
       
       
       
            redis.clients
            jedis
       
       
       
            org.aspectj
            aspectjweaver
       
       
       
            org.apache.commons
            commons-lang3
       
       
       
            com.google.guava
            guava
           






请到「今天看啥」查看全文