利用ajax+jsp+servlet实现网页验证码的生成

效果如下。

点击9888的验证码,可以重新获取验证码。

实现方法主要是ajax+servlet+jsp

ajax部分(这段js需要在页面加载完后执行,不让可能找不到放图片的位置)

//向AjaxGet这个servlet发送post消息

function verification(){
    http_request2.open("POST","../AjaxGet",true);
    http_request2.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    http_request2.onreadystatechange = callback;  
    http_request2.send("verificationR=true");
       
}

//回调函数,http_request2.onreadystatechange会监控页面的变化。当status为200(请求成功),readyState为4(处理完毕),将Verification-pic这个img的图片src属性设置为返回的base64图片。


function callback() {
    var verificationImg = document.getElementById("Verification-pic");
    if(http_request2.readyState==4&&http_request2.status==200){
        verificationImg.src = "data:image/jpeg;base64,"+http_request2.responseText;
    } 

//点击验证码,发生刷新
function refulshVerfication(){
    verification();
}

//定义http_request2,兼容不同属性的浏览器
var http_request2;
if(window.XMLHttpRequest){
    http_request2 = new XMLHttpRequest();
}else if(window.ActiveXObject){
    try{
        http_request2 = new ActiveXObject("Msxml2.XMLHTTP");
    }catch(e){
        try{
            http_request2 = new ActiveXObject("Microsoft.XMLHTTP");
        }catch(e){}
    }
}
verification();

 servlet部分

package baseClass;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.tomcat.util.codec.binary.Base64;

//主要负责处理ajax响应
public class AjaxGet extends HttpServlet {
    public AjaxGet() {}
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)  
                throws ServletException, IOException {  

                    //设置一些响应头信息,禁止缓存
                    response.setContentType("image/jpeg"); 
                    response.setHeader("Prama", "no-cache");
                    response.setHeader("Coche-Control", "no-cache");
                    response.setDateHeader("Expires", 0);
                    PrintWriter output = response.getWriter(); 
//                  ServletOutputStream  output = response.getOutputStream();
                    try {

//由于我这里该类负责响应注册页面和登录页面的验证码生成,所以会有两个。
                        String verificationL = request.getParameter("verificationL"); 
                        String verificationR = request.getParameter("verificationR"); 
                        System.out.println(verificationR);
                        System.out.println(verificationL);
                        if((verificationL!=null && verificationL.equals("true")) || (verificationR!=null && verificationR.equals("true"))) {  

//Verification这个类负责生成验证码,
                            Verfication verificationImg = new Verfication();

//Verification.getString()返回字符串类型的验证码,createVerification返回的是BufferedImage的图像,将验证码的字符串放在session中,以便之后对用户输入进行比对。放在session中安全一点。前端不可直接读取。
                            HttpSession session = request.getSession(true);
                            if(verificationL!=null && verificationL.equals("true"))
                                session.setAttribute("vercodeL", verificationImg.getString());
                            else
                                session.setAttribute("vercodeR", verificationImg.getString());
                            ByteArrayOutputStream out = new ByteArrayOutputStream();

//需要对BufferedImage类型转化成字符串类型的base64格式,返回。在前端的ajax引擎可以监控到页面的返回变化,获得base64编码
                            ImageIO.write(verificationImg.createVerification(),"JPG",out);
                            String s = new String(Base64.encodeBase64(out.toByteArray()),"utf-8");
                            //转化未base64
                            System.out.println(s);
                            output.write(s);
                            
                        }  
                        else {  
                            System.out.println("非验证");  
                        }  
                    } finally {   
                        output.close();  
                    }  
                }   
     //这个是HttpServlet的函数,这里进行重写,主要用于监控向该servlet类发送的post,get信息。
    protected void doGet(HttpServletRequest request,HttpServletResponse response)  throws ServletException,IOException{
        System.out.println("Get Infornation");
        doPost(request, response);        
    }
    protected void doPost(HttpServletRequest request,HttpServletResponse response)  throws ServletException,IOException{
        System.out.println("Post Infornation");
        processRequest(request, response);  
    }
}

servlet注册(写在web.xml文件中)

 <servlet>  
        <servlet-name>AjaxGet</servlet-name>  
        <servlet-class>baseClass.AjaxGet</servlet-class>  
    </servlet>  
    <servlet-mapping>  
        <servlet-name>AjaxGet</servlet-name>  
        <url-pattern>/AjaxGet</url-pattern>  
    </servlet-mapping> 

Verification类(生成验证码)

package baseClass;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;
//产生验证码
public class Verfication {
    public void Verification() {}

//保存验证码的字符串
    private StringBuffer sbf = new StringBuffer();
    protected BufferedImage createVerification() {

//图片的宽度和高度
        int width = 100;
        int height = 30;

//设置图片为RGB三色
        BufferedImage verfication = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
        Graphics g = verfication.getGraphics();
        Random random = new Random();

//设置背景色。我这里是偏向绿色的
        g.setColor(new Color(random.nextInt(100),200,random.nextInt(100)));

//用上面的颜色填充整个图片
        g.fillRect(0, 0, width, height);

//向图片中写入四个字符
        for(int i=0;i<4;i++) {
            g.setColor(Color.black);
            g.setFont(new Font("华中隶书",Font.BOLD|Font.ITALIC,25));
            int n = random.nextInt(10);
            sbf.append(n);

//Graphics.drawString()这个函数的三个参数字符,坐标x,坐标y。这个坐标是字符左下角的坐标,不是一般的左上角
            g.drawString(""+n, i*15+20, 22);
        }
        System.out.println(verfication);

//返回bufferedImage的验证码图片
        return verfication;
    }
    public StringBuffer getString() {
        return sbf;
    }
}
 

 

jsp部分就不贴了,无非就是将用户输入的验证码和上面我们保存在session中的验证码比对一下。

基本上,一个动态的验证码就这样实现了。就是图片有点丑。后期需要再改进一下,并添加一些干扰点。防止爬虫直接通过ocr解析出验证码。

这里使用的主要是ajax和servlet的交互实现验证码的动态生成。 直接用ajax+jsp也可以实现的,就是丑了点。这样分成三块。

实现前后端分离。看着舒服点,下次servlet也可以复用。

 

制作过程中遇见了几个卡了很久的问题

主要是ajax和servlet的传输。刚开始时一直得不到数据,主要的问题是路径问题,以及对于servlet理解不足(一点理解也没有,直接开干,结果卡了好久2333)

1.Servlet类要在web.xml中注册才有效果

2.Servlet类(或者说所有在eclipse 的java web项目中的可调用类)都是指.class编译后的类。所以实际地址是.class类的地址。默认设置下在同个项目中引用地址只需要写 包名.类名 即可,如上面我的AjaxGet注册时,<servlet-class>中写的时baseClass.AjaxGet(前缀路径eclipse已经帮你考虑进去了)。

3.我一开始以为servlet是一个类,不可以直接访问的。我将servlet的web注册里的<url-pattern></url-pattern>写上了发送消息的页面的路径(我以为这个url-pattern是监控发送方来源的,现在想想有点蠢,如果是监控发送方来源的,那该页面的所有消息不都会被servlet截取了么,而且一个servlet只能处理一个网页的消息了。。。),ajax里的请求路径写的是jsp的路径。结果死活得不到消息。实际上url-pattern是监控请求目的地的,也就是接收方的。我这里的AjaxGet类就是接受方,url-pattern过滤匹配请求消息的地址,如果目的方路径是ajaxGet结尾的,ajaxGet类才会处理信息(url-pattern还有好几种匹配方式,详情见该博客https://www.cnblogs.com/canger/p/6084846.html)。

4.js跳转到另一个页面,如果是相对地址,跳转地址应该是相对于引用该js的页面。

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值