SpringBoot后端验证码的实现示例

 更新时间:2024年08月16日 10:46:03   作者:Alphamilk  
为了防止网站的用户被通过密码典爆破,引入验证码的功能是十分有必要的,本文主要介绍了SpringBoot后端验证码的实现示例,具有一定的参考价值,感兴趣的可以了解一下

一、简介

为了防止网站的用户被通过密码典爆破。引入验证码的功能是十分有必要的。而前端的验证码又仅仅是只防君子不防小人。通过burpsuit等工具很容易就会被绕过。所以后端实现的验证码才是对用户信息安全的一大重要保障。

实现思路:

1.引入图形生成的依赖

2.生成随机4字符,并制作成图片

3.对图片进行Base64形式数据进行传输

4.前端显示

二、引入依赖

<!--        验证码模块-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>

三、验证码生成工具类

public class CaptchaUtil {

    private static final int WIDTH = 200;
    private static final int HEIGHT = 75;
    private static final int FONT_SIZE = 36;
    private static final String DEFAULT_FONT = "Arial";

    /**
     * 生成验证码图像.
     *
     * @param captchaText 验证码原始文本
     * @return Base64编码的图像字符串
     */
    public static String generateCaptchaImage(String captchaText) {
        if (captchaText == null || captchaText.isEmpty()) {
            throw new IllegalArgumentException("Captcha text cannot be null or empty.");
        }

        // 创建图像和图形上下文
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = (Graphics2D) image.getGraphics();

        // 设置背景颜色
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, WIDTH, HEIGHT);

        // 绘制验证码文本
        g.setFont(new Font(DEFAULT_FONT, Font.BOLD, FONT_SIZE));
        g.setColor(getRandomColor());
        g.drawString(captchaText, 45, 50);

        // 添加随机线条作为干扰
        addNoiseLines(g);

        // 关闭图形上下文
        g.dispose();

        // 将图像转换为Base64编码的字符串
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            ImageIO.write(image, "png", baos);
            return Base64.getEncoder().encodeToString(baos.toByteArray());
        } catch (Exception e) {
            throw new RuntimeException("Error generating captcha image", e);
        }
    }

    private static void addNoiseLines(Graphics2D g) {
        for (int i = 0; i < 5; i++) {
            g.setColor(getRandomColor());
            g.drawLine(
                    getRandomNumber(WIDTH),
                    getRandomNumber(HEIGHT),
                    getRandomNumber(WIDTH),
                    getRandomNumber(HEIGHT)
            );
        }
    }

    private static Color getRandomColor() {
        return new Color((int) (Math.random() * 255),
                         (int) (Math.random() * 255),
                         (int) (Math.random() * 255));
    }

    private static int getRandomNumber(int bound) {
        return (int) (Math.random() * bound);
    }
}

四、通过Http Session存放验证码与验证

获取(a-z A-Z 0-9)随机四位的验证码功能:

  // 登陆时候获取验证码
    @ApiOperation("获取验证码功能")
    @GetMapping("/GetCaptcha")
    public String GetCaptcha(HttpSession session) {

//        随机生成四位验证码原始数据
        String allowedChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        String randomString = generateRandomString(allowedChars, 4);
        System.out.println("captchaCode " + randomString);

        // 将验证码保存到session中
        session.setAttribute("captcha", randomString); // 使用方法参数session
        String ImageByBase64 = CaptchaUtil.generateCaptchaImage(randomString);
        return ImageByBase64;
    }

用户登陆时候校验验证码功能:

// 实现登陆功能
    @ApiOperation("用户登陆功能")
    @PostMapping("/login")
    public Result Login(@RequestBody LoginDTO loginDTO, HttpSession session) { // 使用同一个HttpSession参数

        String captcha = (String) session.getAttribute("captcha");

        log.info("用户调用login方法");
        if (loginDTO.getCaptcha() == null || !loginDTO.getCaptcha().equalsIgnoreCase(captcha)) {
            session.removeAttribute("captcha");
            return Result.error("验证码出错了噢!");
        }

        // 对密码进行md5加密
        String encryptToMD5 = MD5Util.encryptToMD5(loginDTO.getPassword());

        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getAccount, loginDTO.getAccount())
                .eq(User::getPassword, encryptToMD5);

        User user = userService.getOne(lambdaQueryWrapper);
        if (user == null) {
            return Result.error("很抱歉,查不到此用户");
        }
        user.setPassword("xxxxx");
        return Result.success(user);
    }

五、前端显示Base64格式的图片

前端实现注册的表单

<el-tab-pane label="登陆" name="first">
                <el-form :model="loginForm" ref="loginFormRef" label-width="80px">
                  <el-form-item label="用户名:">
                    <el-input v-model="loginForm.account"></el-input>
                  </el-form-item>
                  <el-form-item label="密码:">
                    <el-input v-model="loginForm.password" show-password></el-input>
                  </el-form-item>
                  <el-form-item label="验证码">
                    <el-input v-model="loginForm.captcha" style="width: 20%;"></el-input>
                    <img :src="captchaImageUrl" alt="验证码" @click="refreshCaptcha" id="captchaImage">
                  </el-form-item>
                </el-form>
              </el-tab-pane>

 先设置为空

export default {
  data() {
    return {
      captchaImageUrl: '', // 初始化为一个空字符串
    }
  },

在点击登陆按钮后,执行getCaptcha函数并设置captchaImageUrl的回显格式为Base64

  fetchCaptcha() {
      axios.get('/api/user/GetCaptcha')
        .then(response => {

          this.captchaImageUrl = 'data:image/png;base64,' + response.data;
        })
        .catch(error => {
          console.error('获取验证码失败:', error);
        });
    },

最后进行测试:

注意:实现完成验证码功能后,需要注意用户的操作。如果登陆失败,刷新页面,切换页面。都需要重新更新验证码!

到此这篇关于SpringBoot后端验证码的实现示例的文章就介绍到这了,更多相关SpringBoot后端验证码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • Java调用C++动态库超详细步骤讲解(附源码)

    Java调用C++动态库超详细步骤讲解(附源码)

    C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,这篇文章主要介绍了Java调用C++动态库的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-04-04
  • java中的正则操作方法总结

    java中的正则操作方法总结

    关于正则表达式的使用,更多的是自己的经验,有兴趣可以参阅相关书籍。这里主要写一下java中的正则操作方法
    2013-10-10
  • 解决springboot中配置过滤器以及可能出现的问题

    解决springboot中配置过滤器以及可能出现的问题

    这篇文章主要介绍了解决springboot中配置过滤器以及可能出现的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • java实现入栈push和出栈pop过程

    java实现入栈push和出栈pop过程

    文章详细介绍了栈的概念、特点以及如何使用数组和链表实现栈,通过入栈(push)和出栈(pop)操作,展示了栈的数据处理过程,并提供了具体的代码实现
    2024-12-12
  • eclipse springboot工程打war包方法及再Tomcat中运行的方法

    eclipse springboot工程打war包方法及再Tomcat中运行的方法

    这篇文章主要介绍了eclipse springboot工程打war包方法及再Tomcat中运行的方法,本文图文并茂给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-08-08
  • 从最基本的Java工程搭建SpringMVC+SpringDataJPA+Hibernate

    从最基本的Java工程搭建SpringMVC+SpringDataJPA+Hibernate

    本文会介绍从一个最基本的java工程,到Web工程,到集成Spring、SpringMVC、SpringDataJPA+Hibernate,本文介绍的非常详细,具有参考借鉴价值,感兴趣的朋友一起学习吧
    2016-05-05
  • Java多线程:生产者与消费者案例

    Java多线程:生产者与消费者案例

    这篇文章主要介绍了Java并发编程中的生产者与消费者模型简述,多线程并发是Java编程中最终要的部分之一,需要的朋友可以参考下,希望能给你带来帮助
    2021-07-07
  • java 使用ConcurrentHashMap和计数器实现锁

    java 使用ConcurrentHashMap和计数器实现锁

    这篇文章主要介绍了java 使用ConcurrentHashMap和计数器实现锁的相关资料,需要的朋友可以参考下
    2017-05-05
  • 如何使用Java实现请求deepseek

    如何使用Java实现请求deepseek

    这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-02-02
  • 详解java中List中set方法和add方法的区别

    详解java中List中set方法和add方法的区别

    本文主要介绍了详解java中List中set方法和add方法的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08

最新评论