当前位置:   article > 正文

验证码功能的简单实现(完整代码+详解)_验证码功能怎么实现

验证码功能怎么实现

介绍

        验证码,作为一种基本的安全措施,帮助在用户验证过程中防止自动化滥用。在这篇博客中,我将分享如何在 Java Web 应用程序中从头开始实现一个简单但有效的验证码功能

效果图如下:

注:本文仅介绍验证码功能的原理和简单实现,大家应根据具体应用场景和需求对代码做出修改和完善

环境与技术栈

环境和技术栈

  • 开发环境:IntelliJ IDEA
  • 后端技术:Java, Servlet
  • 前端技术:HTML, JavaScript
  • 工具类CaptchaUtils.java

实现步骤:

  • 生成验证码图像:使用 Java 的图形和文本 API,如 java.awt 包中的类,来生成包含随机字符的图像。可以使用 BufferedImage 类创建图像,并用 Graphics2D 类来绘制随机生成的字符和干扰线等。
  • 存储验证码信息:生成的验证码需要在服务器端进行存储,以便验证用户输入的验证码是否正确。这通常通过会话(Session)来实现。
  • 提供刷新功能:允许用户通过点击“换一换”来获取新的验证码。这通常涉及到一个 JavaScript 函数,它会发起一个请求到服务器以获取新的验证码图像。
  • 前端展示:在用户界面上显示验证码图像,并提供一个输入框供用户输入验证码。同时,提供一个“换一换”链接,用户点击连接或者验证码图像可以刷新验证码。
  • 验证用户输入:当用户提交表单时,后端将检查用户输入的验证码与会话中存储的验证码是否匹配。

步骤实现与解析:

一.创建验证码工具类

        在 Java Web 应用程序中实现验证码功能的核心在于 CaptchaUtils 工具类。这个类负责生成验证码图片并输出到客户端。以下是这个类的关键功能以及它们如何协同工作:

  1. 生成随机字符串  :生成随机字符串作为验证码的文本。首先定义一个包含所有可能字符(大写字母、小写字母、数字)的字符串,然后使用 Java 的 Random 类来随机选择其中的字符来构建一个指定长度的验证码字符串。
  2. 创建图像:创建一个包含验证码文本的图像。使用 BufferedImage 类来创建空白图像,最后利用 Graphics2D 对象在图像上绘制生成的随机字符串。可以设置字体、大小和颜色以增强视觉效果和安全性。
  3. 增加噪点和干扰线:通过添加噪点和干扰线使自动识别变得更困难。在图像上随机绘制小点和线条。这些干扰元素增加了验证码破解的难度,同时对人类用户的识别影响较小。
  4. 输出图像:将生成的验证码图像输出到客户端。使用 ImageIO.write 方法将 BufferedImage 输出到 HttpServletResponse 的输出流中。

完整代码如下:

  1. package zua.util;
  2. import javax.imageio.ImageIO;
  3. import javax.servlet.http.HttpServletResponse;
  4. import java.awt.*;
  5. import java.awt.image.BufferedImage;
  6. import java.io.IOException;
  7. import java.util.Random;
  8. public class CaptchaUtils {
  9. //定义验证码图像属性
  10. private static final int WIDTH = 80;//图像宽度
  11. private static final int HEIGHT = 40;//图像高度
  12. private static final int LENGTH = 4;//验证码字符数量
  13. private static final Random random = new Random();// 用于生成随机数,便于设置rgb参数
  14. /**
  15. * 创建验证码图像并返回验证码上的文本
  16. *
  17. * @param response HttpServletResponse, 用于输出图像到客户端
  18. * @return 返回生成的验证码文本
  19. */
  20. public static String createCaptchaImage(HttpServletResponse response) {
  21. // 创建BufferedImage对象,这是一个包含图像数据的缓冲区
  22. BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
  23. // 获取Graphics2D对象,可以在图像上进行绘制
  24. Graphics2D g = image.createGraphics();
  25. // 设置背景色为白色并填充整个图像区域
  26. g.setColor(Color.WHITE);
  27. g.fillRect(0, 0, WIDTH, HEIGHT);
  28. // 设置字体,使用Arial字体,加粗,大小20
  29. g.setFont(new Font("Arial", Font.BOLD, 20));
  30. // 随机生成验证码文本字符
  31. String captchaText = generateRandomText(LENGTH);
  32. int x = 10; // 横坐标开始位置
  33. // 逐个绘制验证码中的字符
  34. for (char c : captchaText.toCharArray()) {
  35. // 随机生成字符颜色(rgb)
  36. g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
  37. // 绘制字符,并随机调整字符的垂直位置
  38. g.drawString(String.valueOf(c), x, 20 + random.nextInt(20));
  39. x += 20;// 将横坐标移动到下一个字符的绘制位置
  40. }
  41. // 添加噪点,使图像中的验证码不易被自动识别
  42. g.setColor(Color.LIGHT_GRAY);
  43. for (int i = 0; i < 20; i++) {
  44. int x1 = random.nextInt(WIDTH);
  45. int y1 = random.nextInt(HEIGHT);
  46. int x2 = random.nextInt(12);
  47. int y2 = random.nextInt(12);
  48. g.drawLine(x1, y1, x1 + x2, y1 + y2);// 绘制一条小线段,代表噪点
  49. }
  50. // 完成图像的绘制,释放图形上下文使用的系统资源
  51. g.dispose();
  52. // 设置响应内容类型为JPEG图像
  53. response.setContentType("image/jpeg");
  54. try {
  55. // 将创建的图像写入响应的输出流中
  56. ImageIO.write(image, "JPEG", response.getOutputStream());
  57. // 刷新输出流,确保图像数据完整发送
  58. response.getOutputStream().flush();
  59. } catch (IOException e) {
  60. e.printStackTrace();
  61. }
  62. // 返回生成的验证码文本
  63. return captchaText;
  64. }
  65. /**
  66. * 生成随机文本,用于验证码
  67. *
  68. * @param length 需要生成的文本长度
  69. * @return 返回生成的随机文本
  70. */
  71. private static String generateRandomText(int length) {
  72. // 定义可能出现在验证码中的字符
  73. String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  74. // 随机选择字符并添加到StringBuilder中
  75. StringBuilder sb = new StringBuilder(length);
  76. for (int i = 0; i < length; i++) {
  77. // 将StringBuilder转换为字符串并返回
  78. sb.append(chars.charAt(random.nextInt(chars.length())));
  79. }
  80. return sb.toString();
  81. }
  82. }

二.Servlet处理

        接下来,我们创建 CaptchaServlet 类来处理生成验证码的请求。在 doGet 方法中,我们调用 CaptchaUtils 来生成图像并将验证码文本保存在 session 中。在 doPost 方法中,我们比较用户输入的验证码和 session 中设定的的验证码。

代码如下:

  1. package zua.servlet;
  2. import com.google.gson.Gson;
  3. import zua.util.CaptchaUtils;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.annotation.WebServlet;
  6. import javax.servlet.http.HttpServlet;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import javax.servlet.http.HttpSession;
  10. import java.io.Console;
  11. import java.io.IOException;
  12. import java.io.PrintWriter;
  13. @WebServlet("/captcha")
  14. public class CaptchaServlet extends HttpServlet {
  15. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  16. // 创建验证码图片并返回图片上的文本
  17. String captchaText = CaptchaUtils.createCaptchaImage(response);
  18. // 将验证码文本保存到Session中
  19. HttpSession session = request.getSession();
  20. session.setAttribute("captcha", captchaText);
  21. }
  22. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  23. // 获取用户输入的验证码
  24. String userInputCaptcha = request.getParameter("captcha");
  25. // 从Session中获取真正的验证码
  26. HttpSession session = request.getSession();
  27. String realCaptcha = (String) session.getAttribute("captcha");
  28. // 比较用户输入的验证码和真正的验证码是否一致
  29. // 设置响应类型为JSON
  30. response.setContentType("application/json");
  31. PrintWriter out = response.getWriter();
  32. Gson gson=new Gson();//gson需要相应jar包,如没有下面选其一种方式即可:
  33. /*
  34. * maven:
  35. * <dependency>
  36. <groupId>com.google.code.gson</groupId>
  37. <artifactId>gson</artifactId>
  38. <version>2.10.1</version>
  39. </dependency>
  40. *
  41. * jar下载路径:
  42. * https://mvnrepository.com/artifact/com.google.code.gson/gson/2.10.1
  43. * */
  44. String json;
  45. if (userInputCaptcha != null && userInputCaptcha.equalsIgnoreCase(realCaptcha)) {
  46. json=gson.toJson("success");
  47. } else {
  48. json=gson.toJson("fail");
  49. }
  50. out.write(json);
  51. }
  52. }

 注意:示例中用的gson格式数据,需要下载jar包或在pow里添加依赖,代码中已给出下载地址和maven依赖,根据需求选用其一即可

三.客户端实现

        在 HTML 页面中,我们使用一个 img 标签来显示验证码图像,并提供一个刷新链接。JavaScript 用于处理验证码的刷新和表单提交。

代码如下:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Captcha Example</title>
  6. </head>
  7. <body style="text-align: center">
  8. <!-- 用户输入验证码的文本框 -->
  9. <input type="text" name="captcha" id="captcha" style="width: 160px;height: 40px"/>
  10. <!-- 显示验证码图像 -->
  11. <a href="#" onclick="refreshCaptcha(); return false;">
  12. <img src="/web/captcha" id="captchaImage" alt="Captcha" />
  13. </a>
  14. <!-- 用户点击后刷新验证码的链接 -->
  15. <a href="#" onclick="refreshCaptcha(); return false;">换一换</a><br>
  16. <span id="error" style="color: red"></span><br>
  17. <input type="button" value="提交" id="btn">
  18. <script type="text/javascript">
  19. // 当用户点击“换一换”链接时,调用此函数以刷新验证码图像
  20. function refreshCaptcha() {
  21. var captchaImage = document.getElementById('captchaImage');
  22. // 更新图像的src属性,因为是get请求,所以要在后面添加一个时间戳以防止浏览器缓存图像
  23. captchaImage.src = '/web/captcha?' + new Date().getTime();
  24. }
  25. //输入框获得焦点时擦除错误信息
  26. document.getElementById('captcha').onclick=function (){
  27. document.getElementById("error").innerHTML="";
  28. }
  29. //点击提交时检查验证码
  30. document.getElementById('btn').onclick=function (){
  31. const captcha = document.getElementById('captcha').value.trim();//获得用户输入值
  32. if (captcha===""){//用户输入为空时提示错误信息
  33. document.getElementById("error").innerHTML='请输入验证码';
  34. }else {//用户输入格式正确则发送ajax请求
  35. fetch('/web/captcha', {
  36. method: 'POST', // 使用 POST 方法提交数据
  37. headers: {
  38. 'Content-Type': 'application/x-www-form-urlencoded' // 指定请求的内容类型
  39. },
  40. body: 'captcha='+ captcha //键=值格式
  41. })
  42. .then(response => response.json()) // 解析文本响应
  43. .then(data => {
  44. console.log(data)
  45. if (data==="success") {
  46. alert('验证成功')
  47. } else {
  48. refreshCaptcha();
  49. document.getElementById("error").innerHTML='验证码错误,请重新输入';
  50. }
  51. })
  52. .catch(error => console.error('Error: ', error));
  53. }
  54. }
  55. </script>
  56. </body>
  57. </html>
注:注意服务请求路径要根据自己的项目结构进行。示例中路径/web/captcha是一个指向 CaptchaServlet 的请求路径。这个路径在 CaptchaServlet 类上使用 @WebServlet 注解定义
客户端接收图像的过程解析:

1.在HTML中放置一个<img>标签:
        这个<img>标签有一个src属性,指向服务器上的验证码图片资源。例如,<img src="captcha" id="captchaImage" alt="Captcha" />。当浏览器解析到这个标签时,它会向服务器发送一个GET请求以获取src属性指定的资源。

2.服务器生成图像:
        当请求到达服务器,并被映射到你的CaptchaServlet时,doGet方法会被调用。在doGet方法中,CaptchaUtils.createCaptchaImage(response);会负责生成一个图像,并将其写入到响应的输出流中。

3.响应与图像数据:
        服务器响应请求并将图像数据作为响应体发送回客户端。此时,响应的MIME类型应该被设置为图像的MIME类型(如image/png)。

4.浏览器接收并渲染图像:
        浏览器接收到包含图像数据的响应后,就会在<img>标签的位置渲染图像。

5.刷新验证码
        当用户点击“换一换”时,refreshCaptcha函数会被调用。这个函数会通过更改<img>标签的src属性来强制浏览器重新请求验证码。它通过附加当前时间戳来确保请求不会被浏览器缓存,从而获取新的验证码图像。

        所以,客户端接收图像的关键在于<img>标签的src属性指向你的CaptchaServlet,它负责生成和发送图像数据。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/632840
推荐阅读
相关标签
  

闽ICP备14008679号