Spring Boot实现登录验证码功能的案例详解

Spring Boot实现登录验证码功能的案例详解

简介

最近,我在开发一个基于Spring Boot的Web应用程序时,需要实现一个登录验证码功能,以确保用户输入有效并防止暴力破解。在研究后,我发现可以通过添加一些依赖项和编写一些代码来轻松地实现此功能。在本文中,我将与您分享实现登录验证码功能的详细步骤。

步骤

步骤1:添加依赖

为了实现登录验证码功能,我们需要在Spring Boot项目中添加以下依赖项:

<!-- Spring Boot Web Starter -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Spring Boot Thymeleaf Starter -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<!-- Spring Boot Validation Starter -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

<!-- Google Guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>19.0</version>
</dependency>

<!-- Google Guava图像处理库 -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava-image</artifactId>
    <version>19.0</version>
</dependency>

<!-- 生成随机数工具 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.2.1</version>
</dependency>

步骤2:创建验证码API

为了创建验证码API,我们需要在Spring Boot应用程序中创建一个REST API Endpoint。我们将使用Google Guava创建验证码图像,并将其返回到客户端。以下是我们创建的验证码API:

@RestController
@RequestMapping("/api/v1")
public class CaptchaApiController {

    private final int WIDTH = 100;
    private final int HEIGHT = 35;
    private final int LENGTH = 4;

    private final Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(1000).build();

    @GetMapping(value = "/captcha", produces = MediaType.IMAGE_JPEG_VALUE)
    public ResponseEntity<byte[]> createCaptcha(HttpServletResponse response) throws Exception {
        String captcha = RandomStringUtils.randomAlphanumeric(LENGTH);
        byte[] bytes = createCaptchaImage(captcha);
        cache.put(captcha.toLowerCase(), captcha.toLowerCase());

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.IMAGE_JPEG);
        headers.setContentLength(bytes.length);
        return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
    }

    @GetMapping("/captcha/check")
    public boolean checkCaptcha(@RequestParam String captcha) {
        return Strings.isNullOrEmpty(captcha) || !captcha.matches("[a-zA-Z0-9]{4}") || !cache.asMap().containsKey(captcha.toLowerCase());
    }

    private byte[] createCaptchaImage(String captchaText) throws IOException {
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics graphics = image.getGraphics();
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0, 0, WIDTH, HEIGHT);
        graphics.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 22));
        for (int i = 0; i < captchaText.length(); i++) {
            graphics.setColor(new Color((int) (Math.random() * 255), (int) (Math.random() * 255), (int) (Math.random() * 255)));
            graphics.drawString(Character.toString(captchaText.charAt(i)), 15 * i + 5, 20 + (int) (10 * Math.random()));
        }
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(image, "jpeg", outputStream);
        return outputStream.toByteArray();
    }

}

根据以上代码,我们可以看到 createCaptcha 返回一个byte数组,这是使用Java的内置API实现验证码图像生成的数据,利用响应头指定响应数据格式为JPEG,它可用作REST服务API进行调用。另外,我们还可以看到 checkCaptcha 用于验证验证码是否匹配。

步骤3:创建验证码表单

我们需要将验证码添加到登录表单中,以便用户输入验证码。以下是我们创建的登录表单:

<form method="post" action="/login">
    <div>
        <label for="username">用户名 :</label>
        <input id="username" type="text" placeholder="请输入用户名" name="username" required="required"/>
    </div>
    <div>
        <label for="password">密码 :</label>
        <input id="password" type="password" placeholder="请输入密码" name="password" required="required"/>
    </div>
    <div>
        <label for="captcha">验证码 :</label>
        <input id="captcha" type="text" placeholder="请输入验证码" name="captcha" required="required"/>
        <img id="captcha-img" alt="验证码" src="/api/v1/captcha"/>
    </div>
    <button type="submit">登录</button>
</form>

在上面的表单中,我们添加了一个图像元素到 img 标记并使用 src 属性设置图像URL。在加载页面时,将调用 api / v1 / captcha 端点来获取验证码图像。除此之外,我们还添加了一个输入框来让用户输入验证码。

步骤4:验证用户

最后,我们需要创建另一个Endpoint,以验证用户输入的用户名、密码和验证码是否正确。以下是我们创建的验证代码:

@PostMapping("/login")
public ModelAndView login(@RequestParam String username, @RequestParam String password, @RequestParam String captcha, HttpSession session) {
    ModelAndView modelAndView = new ModelAndView();
    boolean validCaptcha = !checkCaptcha(captcha);
    boolean validUser = userRepository.existsByUsername(username) && passwordEncoder.matches(password, userRepository.findByUsername(username).getPassword());
    if (validCaptcha && validUser) {
        session.setAttribute("username", username);
        modelAndView.setViewName("redirect:/dashboard");
    } else {
        modelAndView.clear();
        modelAndView.setViewName("redirect:/login");
        modelAndView.addObject("errorMessage", "用户名或密码错误");
    }
    return modelAndView;
}

在上述代码中,我们首先验证验证码是否与 captcha 相同,如果相同,则通过验证。如果验证码验证通过,则验证用户的用户名和密码。如果验证通过,则将其添加到当前会话中,然后将用户重定向到仪表板页面。

示例

为了更好地说明博客文章的内容,请参见以下两个互联网示例::

  1. Java Home Cloud - Spring Boot实现验证码
  2. Spring Boot Captcha App - Github

这些示例提供了一个Spring Boot应用程序,帮助您快速获取有关如何实现登录验证码功能的真实和具体的实现。

结论

在本文中,我们详细探讨了Spring Boot实现图形验证码的方法,并提供了两个示例代码引用供读者参考。使用Spring Boot和其他依赖项,我们可以轻松地实现网站中的验证码功能,以降低暴力攻击和垃圾回收的风险。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Boot实现登录验证码功能的案例详解 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • SpringBoot集成kafka全面实战记录

    下面我将为大家详细讲解SpringBoot集成Kafka全面实战记录的完整攻略。 1. 环境搭建 在开始之前,我们需要先完成环境搭建,包括安装JDK、安装Kafka、创建Kafka集群等操作。具体的步骤可以参考Kafka官方文档,这里不再赘述。 2. SpringBoot集成Kafka 2.1 引入依赖 首先,在SpringBoot项目中引入Kafka相关的…

    Java 2023年5月20日
    00
  • java.lang.Runtime.exec的左膀右臂:流输入和流读取详解

    Java提供了Runtime.exec()方法来启动一个新进程。该方法可以返回Process对象,通过该对象可以控制和管理子进程的输入、输出以及错误流。这个方法中的参数是一个字符串,它描述了一个shell命令,应该如何来运行这个新的子进程。 为了更好地使用exec()方法,在使用exec()的时候,我们应该学会: 1.正确处理进程输出 2.合并输出流,正确地…

    Java 2023年5月26日
    00
  • 简单谈谈java中匿名内部类构造函数

    Java中匿名内部类是没有名称的内部类,可以用来简化代码的编写。匿名内部类是在使用的时候定义的,它没有构造函数名,创建对象时直接使用new关键字即可,构造函数的参数以及实现的抽象方法直接写在new后面的大括号中。 Java中匿名内部类的语法格式为: new 类或者接口名称(){ //实现类或接口中的抽象方法 } 这样创建的实例是匿名内部类的实例,该实例可以实…

    Java 2023年5月26日
    00
  • Java创建线程的两种方式

    当需要创建线程时,Java提供了两种方式:使用Thread类创建线程和实现Runnable接口创建线程。下面我们分别讲解这两种方式的使用方法。 1. 使用Thread类创建线程 Thread类是Java中用于创建和操作线程的基本类。使用Thread类创建线程可以直接关联想要启动的线程代码,并通过start()方法启动新线程。 示例1:继承Thread类创建线…

    Java 2023年5月18日
    00
  • Java最长公共子序列示例源码

    Java最长公共子序列示例源码可以用于找到两个字符串之间的最长公共子序列。以下是Java最长公共子序列示例源码的完整攻略: 1. 题目描述 给定两个字符串s1和s2,找到它们的最长公共子序列(LCS)。 2. 示例 示例1: 输入:s1 = "abcde", s2 = "ace" 输出:3 解释:最长公共子序列是 &q…

    Java 2023年5月27日
    00
  • springmvc集成shiro登录权限示例代码

    下面是关于SpringMVC集成Shiro登录权限的完整攻略,包含两个示例说明。 SpringMVC集成Shiro登录权限示例代码 Shiro是一个强大的Java安全框架,它提供了身份验证、授权、加密等功能。在SpringMVC中集成Shiro可以帮助我们更好地管理用户的登录和权限。在本文中,我们将介绍如何在SpringMVC中集成Shiro,并提供两个示例…

    Java 2023年5月17日
    00
  • java多线程读写文件示例

    下面是关于“Java多线程读写文件”的完整攻略: Java多线程读写文件示例 多线程读取文件 在Java中,可以通过创建多个线程来同时读取文件,以加快文件读取的速度,提高程序的执行效率。下面是一个简单的Java多线程读取文件示例: import java.io.BufferedReader; import java.io.File; import java.…

    Java 2023年5月19日
    00
  • JAVA+Hibernate 无限级分类

    我可以为你详细讲解“JAVA+Hibernate 无限级分类”的完整攻略。这个攻略的目的是帮助Java开发者使用Hibernate实现无限级分类(即树形结构),以便更高效地组织和管理数据。 什么是无限级分类? 无限级分类又称为多级分类或树形结构分类,是指将一个分类体系无限地层层递进,其中每一项都可以作为父级和子级同时存在。常见的例子包括商品分类、地理位置管理…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部