jsp+Servlet编程实现验证码的方法

下面我来详细讲解“jsp+Servlet编程实现验证码的方法”的完整攻略。

什么是验证码?

验证码(CAPTCHA)是指计算机应用程序为区分用户是真实用户还是计算机程序而推出的一种测试。常见的验证码类型包括数字、字母、滑块等形式,用户需要正确地填写系统生成的图形码信息才能进行下一步操作。

实现验证码的原理

验证码的实现原理是利用了Web开发中的Session机制。当我们访问网站时,会话的ID会被存储在Web服务器端的存储器里。生成的验证码会放在一个Session中存储,并且在前端展示给用户。 用户提交表单时,后台会收到表单提交的数据及验证码,后台程序会从Session中取出验证码并与用户传输的验证码进行比较。如果输入的验证码不正确,后台程序可以拒绝接受表单数据。

实现步骤

在jsp页面中创建验证码的表单,并在后台通过Servlet生成验证码并存储到session中;通过判断session的值与用户输入的值是否一致,来实现验证码的验证。

具体的实现步骤:

  1. 创建验证码图片
    首先,我们需要生成一副随机的验证码图片,可以使用Java的Graphics类,在图片上写入验证码字符串,并增加一些干扰线和干扰点,以使验证码更加难以被识别。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    int width = 120;//定义图片宽度
    int height = 30;//定义图片高度
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);//创建BufferedImage对象
    Graphics g = image.getGraphics();//创建Graphics对象
    //填充背景
    g.setColor(Color.WHITE);
    g.fillRect(0, 0, width, height);
    //产生4个随机字符
    String text = "";
    String base = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    Random random = new Random();
    for (int i = 0; i < 4; i++) {
        //随机颜色
        g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
        //设置字体
        Font font = new Font("宋体", Font.BOLD, 25);
        g.setFont(font);
        //画字符
        char ch = base.charAt(random.nextInt(base.length()));
        g.drawString("" + ch, (20 * i) + 12, 24);
        text = text + ch;
    }
    //干扰线
    for (int i = 0; i < 5; i++) {
        g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
        g.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width), random.nextInt(height));
    }
    //干扰点
    for (int i = 0; i < 30; i++) {
        g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
        g.drawOval(random.nextInt(width), random.nextInt(height), 1, 1);
    }
    //将验证码存入Session
    request.getSession().setAttribute("checkcode", text);
    //response
    response.setContentType("image/jpeg");
    OutputStream os = response.getOutputStream();
    ImageIO.write(image, "jpeg", os);
}
  1. 在jsp页面中使用img标签显示验证码图片
<%@page contentType="text/html;charset=UTF-8" language="java"%>
<html>
<head>
    <meta charset="UTF-8">
    <title>验证码示例</title>
</head>
<body>
    <form action="RegisterServlet" method="post">
        <label>用户名:</label>
        <input name="username"><br>
        <label>密码:</label>
        <input name="password" type="password"><br>
        <label>验证码:</label>
        <input name="checkcode">
        <img src="CheckCodeServlet" alt="验证码" onclick="this.src='CheckCodeServlet?d='+new Date().getTime()"><br>
        <input type="submit" value="注册">
    </form>
</body>
</html>

其中,img标签的src属性指向CheckCodeServlet的地址,onclick事件用来更新验证码图片。

  1. 在Servlet中获取并验证用户输入的验证码
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //获取输入的用户名、密码和验证码
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    String checkcode = request.getParameter("checkcode");
    //从Session中获取验证码
    String code = (String) request.getSession().getAttribute("checkcode");
    //比较验证码
    if(code.equalsIgnoreCase(checkcode)){
        //验证码正确,进行注册操作
        //...
    }else {
        //验证码错误,返回错误提示
        response.getWriter().write("验证码错误!");
    }
}
  1. 防止验证码过期

由于Session的默认过期时间比较短,验证码可能会在过期时间内失效,从而导致验证码验证失败。可以通过在Servlet中设置Session的有效时间来解决这个问题:

@Override
public void init(FilterConfig filterConfig) throws ServletException {
    //在初始化时获取配置的过期时间
    String timeout = filterConfig.getInitParameter("timeout");
    //将timeout转换为long类型
    sessionTimeout = Long.parseLong(timeout);
}

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest)servletRequest;
    HttpServletResponse response = (HttpServletResponse) servletResponse;
    //获取Session
    HttpSession session = request.getSession();
    //设置Session的过期时间为30分钟
    session.setMaxInactiveInterval((int)sessionTimeout);
    filterChain.doFilter(request,response);
    return;
}

示例说明

以下是两条完整的示例说明。

示例一:验证码登陆

如果我们要实现用户登录的时候需要输入验证码,可以在登录表单中加入验证码的输入框,并在后端进行验证码的验证。

登陆表单样式:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
    <center>
        <h2>Welcome</h2>
        <form method="post" action="loginServlet">
            <table>
                <tr>
                    <td>UserName:</td>
                    <td><input type="text" name="username"/></td>
                </tr>
                <tr>
                    <td>Password:</td>
                    <td><input type="password" name="password"/></td>
                </tr>
                <tr>
                    <td>Code:</td>
                    <td><input type="text" name="checkcode"/><img src="CodeServlet" onclick="this.src='CodeServlet?'+new Date().getTime();"/></td>
                </tr>
                <tr>
                    <td colspan="2" align="right"><input type="submit" value="Login"/></td>
                </tr>
            </table>
        </form>
    </center>
</body>
</html>

CodeServlet代码:

package com.myblog.servlet;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

/**
 * Created by gjy on 2021/7/6
 **/
@WebServlet(name = "CodeServlet", urlPatterns = "/CodeServlet")
public class CodeServlet extends HttpServlet {

    private static final long serialVersionUID = 2432440348832509368L;

    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response) throws ServletException, IOException {
        int width = 120;
        int height = 25;
        // 创建BufferedImage对象,设置大小和参数设置
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = image.createGraphics();
        // 创建一个随机数生成器
        int codeCount = 4;// 验证码长度为4
        char code[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".toCharArray();
        // 创建一个字符串,用于存储生成的验证码
        StringBuffer buffer = new StringBuffer();
        // 将验证码绘制到图像中
        // randomCode用于保存随机产生的验证码,以便用户登录后进行验证
        String randomCode = null;
        for (int i = 0; i < codeCount; i++) {
            // 得到随机产生的验证码数字
            String strRand = String.valueOf(code[new Random().nextInt(code.length)]);
            // 用随机产生的颜色将验证码绘制到图像中
            g2d.setColor(new Color(new Random().nextInt(255),
                    new Random().nextInt(255), new Random().nextInt(255)));
            g2d.drawString(strRand, 18 * i + 10, 19);
            buffer.append(strRand);
        }
        // 将生成的验证码保存到session中,跟用户的输入进行比较
        HttpSession session = request.getSession();
        session.setAttribute("checkcode", buffer.toString());
        g2d.dispose();

        response.setContentType("image/jpeg");
        OutputStream outputStream = response.getOutputStream();
        // 输出图像到页面
        ImageIO.write(image, "jpeg", outputStream);
        outputStream.close();
    }

    protected void doPost(HttpServletRequest request,
                          HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

loginServlet代码:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    String checkcode = request.getParameter("checkcode");
    HttpSession session = request.getSession();
    String trueCode = session.getAttribute("checkcode").toString();
    if (checkcode == null || !trueCode.equals(checkcode)) {// 判断验证码是否输入正确
        response.sendRedirect("check.html");
        return;
    }
    System.out.println("The userName is " + username);
    System.out.println("The password is " + password);
    response.sendRedirect("login.jsp");
}

示例二:实现验证码注册

在使用表单进行用户注册时,我们也可以添加验证码输入框,以便验证。

注册页面样式:

<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Register</title>
</head>
<body>
    <h2>Register</h2>
    <form action="RegisterServlet" method="post">
        <table>
            <tr>
                <td><label for="username">Username:</label></td>
                <td><input type="text" id="username" name="username" required></td>
            </tr>
            <tr>
                <td><label for="password">Password:</label></td>
                <td><input type="password" id="password" name="password" required></td>
            </tr>
            <tr>
                <td><label for="checkcode">Verification Code:</label></td>
                <td>
                    <input type="text" id="checkcode" name="checkcode" required>
                    <img src="CodeServlet" onclick="this.src='CodeServlet?' + new Date().getTime();"/>
                </td>
            </tr>
            <tr>
                <td colspan="2" align="center">
                    <input type="submit" value="Register">
                </td>
            </tr>
        </table>
    </form>
</body>
</html>

CodeServlet代码和上面示例一相同,就不再给出。

RegisterServlet代码:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    String checkcode = request.getParameter("checkcode");
    HttpSession session = request.getSession();
    String trueCode = session.getAttribute("checkcode").toString();
    if (checkcode == null || !trueCode.equals(checkcode)) {// 判断验证码是否输入正确
        response.getWriter().append("Incorrect Verification Code!");
        return;
    }
    System.out.println("The userName is " + username);
    System.out.println("The password is " + password);
    response.getWriter().append("Register Success!");
}

总结

至此,“jsp+Servlet编程实现验证码的方法”已经说完了。通过本文,我们了解了验证码的作用与实现原理,并详细讲解了如何通过JSP和Servlet技术实现验证码。对于Web开发中需要验证用户身份的场景,使用验证码是保证安全性的一种常用方法。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:jsp+Servlet编程实现验证码的方法 - Python技术站

(0)
上一篇 2023年6月15日
下一篇 2023年6月15日

相关文章

  • 常用字符集编码详解(ASCII GB2312 GBK GB18030 unicode UTF-8)

    常用字符集编码详解 在计算机中,各种语言的字符需要通过字符编码来表示,常见的字符集编码包括ASCII、GB2312、GBK、GB18030、unicode、UTF-8。下面逐一介绍。 ASCII ASCII(American Standard Code for Information Interchange)是最早的字符编码,将每个字符用7位十进制数表示。编…

    Java 2023年5月20日
    00
  • Spring Data Jpa+SpringMVC+Jquery.pagination.js实现分页示例

    下面我来详细讲解一下“Spring Data Jpa+SpringMVC+Jquery.pagination.js实现分页示例”的完整攻略。 1. 环境准备 首先,我们需要准备好以下环境: JDK 1.8 Spring Boot 2.3.4.RELEASE Spring Data JPA 2.3.4.RELEASE MySQL 8.0.21 Maven 3.…

    Java 2023年5月20日
    00
  • Java日期时间类及计算详解

    Java日期时间类及计算详解 Java中提供了多个日期时间类,用于操作和计算日期和时间。本文将详细介绍Java日期时间类及计算的相关知识。 Date类 Date类是Java中最基本的日期时间类。它表示时间戳,即自1970年1月1日00:00:00至当前日期时间所经过的毫秒数。 获取当前日期时间 要获取当前日期时间,可以使用Date类的无参构造函数和toStr…

    Java 2023年5月20日
    00
  • Spring Boot 应用的热部署配置方法

    下面我将详细讲解 Spring Boot 应用的热部署配置方法。 什么是热部署? 热部署是指在应用运行的过程中,不需要重新启动应用,就能实现应用代码的更新。这在开发调试阶段非常有用,因为可以避免频繁地重启应用,提高开发效率。 Spring Boot 应用的热部署配置方法 方法一:使用 Spring Boot DevTools Spring Boot DevT…

    Java 2023年5月19日
    00
  • java操作oracle数据库示例

    以下是 Java 操作 Oracle 数据库的完整攻略: 环境 在开始之前,需要确定自己的开发环境中是否已经安装好 JDK 和 Oracle 数据库,并且已经配置好了相应的环境变量。如果没有,请先安装和配置好相应的软件和环境。 另外,如果需要在Java中操作Oracle数据库,还需要下载安装 ojdbc 驱动程序,将其放置于项目根目录下或指定的lib目录下。…

    Java 2023年5月19日
    00
  • 注册验证java代码[针对上篇文章]

    下面详细讲解”注册验证Java代码[针对上篇文章]”的完整攻略。 1. 环境准备 本地已经安装了JDK,可以在命令行中输入javac -version和java -version来检查; 集成开发工具,比如Eclipse等; 提前编写好数据库配置文件和表结构。 2. 代码编写 2.1. 后端代码 在后端代码中,我们需要对注册表单提交的信息进行处理,包括对用户…

    Java 2023年5月23日
    00
  • Java循环队列与非循环队列的区别总结

    Java循环队列与非循环队列的区别总结 什么是队列? 队列是计算机科学中一种常见的抽象数据类型,它代表了一组可以按顺序访问的元素,遵循 “先进先出” (FIFO) 的原则,也就是最先进入队列的元素最先被处理和弹出。 非循环队列 非循环队列是最普通的队列,也是最容易实现的。非循环队列采用静态数组或动态数组来实现。队列的读取位置(front) 和写入位置(rea…

    Java 2023年5月26日
    00
  • 深入理解springMVC中的Model和Session属性

    在Spring MVC中,Model和Session属性是常用的数据传递方式。Model属性用于在请求处理期间传递数据,而Session属性用于在多个请求之间传递数据。下面是深入理解Spring MVC中的Model和Session属性的完整攻略: Model属性 1. Model属性的作用 Model属性用于在请求处理期间传递数据。在Spring MVC中…

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