java web验证码实现

验证码实现

网上大都是通过servlet实现的验证码,入下图逻辑:

步骤:
1、请求登录页面时随机生成验证码字符串;
2、将生成对验证码字符串存到session中;
3、根据验证码字符串生成验证码图片,然后将验证码图片输出到客户展示;
4、提交登录请求时用户输入的验证码字符串与session中的字符串做比对。

现在很多人都采用Spring mvc,为了更加灵活,解耦servlet,可以写一个验证码制作器:

import javax.imageio.ImageIO;
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.Calendar;
import java.util.Random;
public class ValidateCodeMaker {
    private int imgWidth = 80; //验证码图片宽度
    private int imgHeight = 30; //验证码图片高度     
    private int charCount = 4;  //验证码字符个数
    public ValidateCodeMaker() {
    }
    public ValidateCodeMaker(int imgWidth, int imgHeight, int charCount) {
        this.imgWidth = imgWidth;
        this.imgHeight = imgHeight;
        this.charCount = charCount;
    }
    //客户端生成验证码图片,并且验证码字符串存session
    public void generateValidateCode(HttpSession session,HttpServletResponse response) throws IOException {
        String validateCode = randomCode(charCount);
        session.setAttribute(Constants.VALIDATE_CODE,validateCode);
        session.setAttribute(Constants.VALIDATE_CODE_TIEM, Calendar.getInstance());
       // request.getSession().setAttribute("validateCode",validateCode);
        BufferedImage image = getCodeImage(validateCode);
        response.setContentType("image/jpeg");
        OutputStream out = response.getOutputStream();
        ImageIO.write(image,"jpeg",out);
    }
    //用户输入的验证码与session中的验证码字符串对比校验
    public static boolean verifyValidateCode(HttpSession session,String checkCode){
        String validateCode = (String) session.getAttribute(Constants.VALIDATE_CODE);
        Calendar validateCodeTime = (Calendar) session.getAttribute(Constants.VALIDATE_CODE_TIEM);
        validateCodeTime.add(Calendar.MINUTE,5);         //验证码5分钟有效期
        Calendar now = Calendar.getInstance();
        if(now.before(validateCodeTime) && validateCode.equals(checkCode.trim().toUpperCase()) ){
            session.removeAttribute(Constants.VALIDATE_CODE);
            session.removeAttribute(Constants.VALIDATE_CODE_TIEM);
            return true;
        }
        return false;
    }
    //生成验证码图片
    public BufferedImage getCodeImage(String validateCode){
        BufferedImage image = 
             new BufferedImage(imgWidth,imgHeight,BufferedImage.TYPE_INT_RGB);  //画布
        Graphics g = image.getGraphics();     //画笔
        Random r = new Random();
        //设置画笔颜色,grb值偏大一些可使背景色偏淡
        g.setColor(new Color(r.nextInt(155)+100,r.nextInt(155)+100,r.nextInt(155)+100)); 
        g.fillRect(0, 0, imgWidth, imgHeight);    //设置验证码图片背景色
        g.setColor(new Color(0, 0, 0));
    //Font:参数1->字体类别  参数2->字体样式 参数3->字体size
        g.setFont(new Font(null,Font.ITALIC+Font.BOLD,20)); 
        g.drawString(validateCode,10,20);         //将字符串画到图片上
        //加上一些干扰线
        for(int i=0;i<8;i++){
            g.drawLine(r.nextInt(80),
                    r.nextInt(30),
                    r.nextInt(80),
                    r.nextInt(30));
        }
        g.dispose();
        return image;
    }
   //生成随机字符串
    public String randomCode(int size){
        String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        String code = "";
        Random r = new Random();
        for(int i=0;i<size;i++){
            code +=chars.charAt(r.nextInt(chars.length()));
        }
        return code;
    }
}


页面中验证码区域:

<label>验证码:</label>
<input name="checkCode">
<img id="img1" src="${request.contextPath}/requestCheckCode" 
    οnclick="this.src='${request.contextPath}/requestCheckCode?' + Math.random();"/>
<a href="javascript:;"
   οnclick="document.getElementById('img1').src='${request.contextPath}/requestCheckCode?' + Math.random();">看不清,换一个</a>

客户端请求时,因为IO开销较大,验证码显示会迟与页面的加载,可采用一点小技巧处理这种情况:

比如:客户端请求时,因为验证码图片是异步加载的,可以先隐藏页面的验证码区域,当某一个输入框失去焦点时在将验证码区域显示出来。

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值