使用Servlet+AJAX+AWT实现网站登录时的图片验证码功能

目录

前言

一.编写登录页login.jsp

二.绘制验证码

三.编写Servlet


前言

为了防止恶意软件对“登录”等需要验证码的功能进行暴力破解,网站通常会使用验证码来增加安全性。验证码通常由一些经处理后的不规则的数字,字母及线条组成,其中线条是为了防止机器人解析验证码的真实内容。这个案例用的知识比较基础,需要用到servlet、Ajax、awt来实现。效果如下图所示,鼠标在输入框失去焦点时,触发校验函数进行验证:


 哈哈哈,这个√和×有点丑啊,凑合看,反正没问题。

一.编写登录页login.jsp

本步主要完成以下的功能:

1.编写登录界面基本的元素

2.编写js程序,监听blur事件,输入框失去焦点时触发的函数

3.在校验函数中用ajax将用户输入的验证码传递给负责比对验证码的servlet

4.servlet对比,如果正确,则会返回√的图片,不正确会返回错×的图片

5.ajax将结果渲染到网页上

login.jsp的代码如下:

<%--
  Created by IntelliJ IDEA.
  User: 害恶细君
  Date: 2021/10/20
  Time: 12:39
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>login</title>
    <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
    <script>
        $(function (){
            //通过验证码输入框的blur事件来触发函数
            $("#checkCodeId").blur(function (){
                let checkCode=$("#checkCodeId").val();
                //在服务器端对验证码进行校验
                $.post("CheckCodeServlet",
                    "checkCode="+checkCode,
                    function (result) {
                    //根据返回的图片路径显示不同的提示图片
                    let resultHTML=$("<img src='"+result+"'height='115px' width='15px'/>");
                    $("#result").html(resultHTML);
                })
            })
        });
        //刷新验证码
        function reload($img){
            $img.attr("src","img.jsp?t="+(new Date().getTime()));
        }
    </script>
</head>
<body>
<table border="0">
    <tr>
        <td>验证码</td>
        <td><input type="text" name="checkCode" id="checkCodeId" size="4"></td>
        <!--点击图片,重新加载验证码,img为验证码图片-->
        <td><a href="javascript:reload($('img'))"><img src="img.png"/></a></td>
        <!--验证码校验结果的图片-->
        <td id="result"></td>
        <td>看不清? 点击验证码更换一张</td>
    </tr>

</table>

</body>
</html>

二.绘制验证码

MIME(Multipurpose Internet Mail Extension)多用途因特网邮件扩展协议。是描述信消息内容的因特网标准,用于设置文本,图像,音频,视频,以及其他应用程序专用的数据类型。开发者可以通过jsp中page指令的contentType属性设置页面的MIME类型。例如:contentType="image/jpeg"表示页面会被JPEG等图片格式。

下面通过设置MIME将一个jsp渲染成jpeg图片,用于生成验证码:

1.先编写img.jsp。代码如下:

<%@ page import="java.awt.*" %>
<%@ page import="java.util.Random" %>
<%@ page import="java.awt.image.BufferedImage" %>
<%@ page import="javax.imageio.ImageIO" %><%--
  Created by IntelliJ IDEA.
  User: 害恶细君
  Date: 2021/10/20
  Time: 16:06
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>img</title>
</head>
<body>
<!--定义一些全局方法-->
<%!
    //随机生成颜色
    public Color getColor(){
        Random random=new Random();
        int r=random.nextInt(256);
        int g=random.nextInt(256);
        int b=random.nextInt(256);
        return new Color(r,g,b);
    }
    //生成验证码(随机生成4位数字)
    public String getNum(){
        int ran= (int) (Math.random()*9000+1000);
        return String.valueOf(ran);
    }
%>

<%
    //禁用浏览器缓存,防止验证码不及时被加载
    response.setHeader("pragma","no-cache");
    response.setHeader("cache-control","no-cache");
    response.setDateHeader("expires",0);
    //设置验证码图片:宽80px,gao30px,颜色类型为RGB
    BufferedImage image=new BufferedImage(80,30,BufferedImage.TYPE_INT_RGB);
    //创建画笔对象graphics
    Graphics graphics=image.getGraphics();
    //填充验证码图片的背景色:从(0,0)开始填充,填充宽度为80px,填充高度为30px
    graphics.fillRect(0,0,80,30);
    /*
    *在验证码图片上随机生成60条干扰线段
    * 线段的起始位置为(xBegin,yBegin),结束位置为(xEnd,yEnd)
    */
    for (int i=0;i<60;i++){
        Random random=new Random();
        int xBegin=random.nextInt(80);
        int yBegin=random.nextInt(30);
        int xEnd=random.nextInt(xBegin+10);
        int yEnd=random.nextInt(yBegin+10);
        //设置线条的颜色
        graphics.setColor(getColor());
        //绘制线条
        graphics.drawLine(xBegin,yBegin,xEnd,yEnd);
    }
    //设置验证码的字体格式:字体为serif,粗体,18像素
    graphics.setFont(new Font("serif",Font.BOLD,18));
    //设置验证码的字体颜色为黑色
    graphics.setColor(Color.black);
    //获取验证码
    String checkcode=getNum();
    //验证码的各个数字之间增加一些间隔(空格)
    StringBuffer sb=new StringBuffer();
    for (int i = 0; i < checkcode.length(); i++) {
        sb.append(checkcode.charAt(i)+" ");
    }
    //从坐标(15,20)开始绘制验证码
    graphics.drawString(sb.toString(),15,20);
    //将验证码的值放入session中,供后续使用
    session.setAttribute("CHECKCODE",checkcode);
    //将验证码绘制成JPEG格式
    ImageIO.write(image,"jpeg",response.getOutputStream());
    out.clear();
    //验证码会被其他页面所引用
    //JPEG格式的验证码生成后,会作为<img/>元素的src属性被其他页面引用
    out=pageContext.pushBody();
%>
</body>
</html>

三.编写Servlet

在这个servlet里校验用户输入的验证码

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 java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/CheckCodeServlet")
public class CheckCodeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取前端输入的验证码
        String checkCodeClient=req.getParameter("checkCode");
        String result= "imgs/wrong.png";
        //获取服务器端session中的验证码
        String checkcodeServlet= (String) req.getSession().getAttribute("CHECKCODE");
        if (checkCodeClient.equals(checkcodeServlet)){
            result="imgs/right.png";
        }
        //以IO的方式,返回result值(提示图片路径)
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter pw =resp.getWriter();
        pw.write(result);
        pw.flush();
        pw.close();
    }
}

okk,终于写完了,没想到居然写了快六千字,代码量有点小多啊。

接下来我要学后端框架了,先从Mybatis开始吧,那我们下期见,拜拜!

采用ajax技术实现的图形验证码,在前端进行验证。验证码信息为图片。每一行代码均有注释,通俗易懂。 实现步骤: 1、创建web工程 2、在jsp页面,编写一个 3、编写一个servlet,在servlet中产生图形验证码 ------------------------------------------------------------ //1、给客户端作出的回应是以图片的方式来回应 response.setContentType("image/jpeg"); //2、创建一个图形缓冲区,用于绘制图形 (宽度,高度,颜色的生成方案) BufferedImage image = new BufferedImage(800,600,BufferedImage.TYPE_INT_RGB); //3、创建一支画笔(图形设备接口)用于绘图 Graphics g = image.getGraphics(); //4、指定图笔的颜色 g.setColor(getColor(200,256)); //5、绘制一个矩形框,作为验证码的背景 g.fillRect(0,0, 800,600); //产生一个输出流,准备把图片以流的方式,输出到客户端 OutputStream out = response.getOutputStream(); //输出在图形缓冲区中,绘制的图片 ImageIO.write(image,"jpg",out); //关闭流 out.close(); //随机生成背景颜色 private Random rd = new Random(); //产生随机数类 public Color getColor(int start,int end){ int r = start+rd.nextInt(end-start); int g = start+rd.nextInt(end-start); int b = start+rd.nextInt(end-start); return new Color(r, g, b);//根据三原色的值,随机在指定范围内,生成一种颜色 } --------------------------------------------------------------------------- 0-120 比较适合文字的颜色 100-200 适合干扰线条的颜色 200-255 适合背景颜色 --------------------------------------------------------------------------- 生成图片中的文字: 1、先编写一个字符串,包含:数字,大小字母 private String s = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 2、在产生背景之后,编写如下代码,产生四个字符(并且,把生成字符,保存在session中,在登录候用来做判断) String code=""; //用于保存生成的四个字符 for(int i=0;i<4;i++){ //生成一个随机数,它的取值范围,一定要在s这个字符串的长度范围之内 int index = rd.nextInt(s.length()); //2 //把index作为下标,来取得字符串的中某一个字符 char c = s.charAt(index); //指定文字的颜色----深色段 g.setColor(getColor(0,120)); //创建一个字体 Font f = new Font("隶书",Font.ITALIC|Font.BOLD,60+rd.nextInt(60)); //把字体关联到画笔 g.setFont(f); code+=c; //把生成的字符连接成一个字符串 //把文字输出到图片上 g.drawString(String.valueOf(c), 100+i*80+rd.nextInt(100),200+rd.nextInt(150)); } request.getSession().setAttribute("code",code);//把生成的验证码信息,存储到session中,登录候,用来作判断 ------------------
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

害恶细君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值