验证码实现

Posted caozz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了验证码实现相关的知识,希望对你有一定的参考价值。

一、springboot实现,用于测试工具类是否可用

1、先写一个生成验证码的工具类,用来生成验证码
package com.jdwa.utill;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Locale;
import java.util.Random;

/**
 * 生成验证码的工具类
 */
public class VerifyCode {
    private static final Logger log = LoggerFactory.getLogger(VerifyCode.class);
    private int width = 100;// 生成验证码图片的宽度
    private int height = 50;// 生成验证码图片的高度
    private String[] fontNames = { "宋体", "楷体", "隶书", "微软雅黑" };
    private Color bgColor = new Color(255, 255, 255);// 定义验证码图片的背景颜色为白色
    private Random random = new Random();
    private String codes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private String text;// 记录随机字符串

    /**
     * 获取一个随意颜色
     *
     * @return
     */
    private Color randomColor() {
        int red = random.nextInt(150);
        int green = random.nextInt(150);
        int blue = random.nextInt(150);
        return new Color(red, green, blue);
    }

    /**
     * 获取一个随机字体
     *
     * @return
     */
    private Font randomFont() {
        String name = fontNames[random.nextInt(fontNames.length)];
        int style = random.nextInt(4);
        int size = random.nextInt(5) + 24;
        return new Font(name, style, size);
    }

    /**
     * 获取一个随机字符
     *
     * @return
     */
    private char randomChar() {
        return codes.charAt(random.nextInt(codes.length()));
    }

    /**
     * 创建一个空白的BufferedImage对象
     *
     * @return
     */
    private BufferedImage createImage() {
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = (Graphics2D) image.getGraphics();
        g2.setColor(bgColor);// 设置验证码图片的背景颜色
        g2.fillRect(0, 0, width, height);
        return image;
    }

    public BufferedImage getImage() {
        BufferedImage image = createImage();
        Graphics2D g2 = (Graphics2D) image.getGraphics();
        StringBuffer sb = new StringBuffer();
        Font f = randomFont();
        System.out.println(f.getFontName());
        System.out.println(f.getFontName(new Locale("zh_CN")));
        for (int i = 0; i < 4; i++) {
            String s = randomChar() + "";
            sb.append(s);
            g2.setColor(randomColor());
            g2.setFont(randomFont());
            float x = i * width * 1.0f / 4;
            g2.drawString(s, x, height - 15);
        }
        this.text = sb.toString();
        drawLine(image);
        return image;
    }

    /**
     * 绘制干扰线
     *
     * @param image
     */
    private void drawLine(BufferedImage image) {
        Graphics2D g2 = (Graphics2D) image.getGraphics();
        int num = 5;
        for (int i = 0; i < num; i++) {
            int x1 = random.nextInt(width);
            int y1 = random.nextInt(height);
            int x2 = random.nextInt(width);
            int y2 = random.nextInt(height);
            g2.setColor(randomColor());
            g2.setStroke(new BasicStroke(1.5f));
            g2.drawLine(x1, y1, x2, y2);
        }
    }

    public String getText() {
        return text;
    }

    public static void output(BufferedImage image, OutputStream out) throws IOException {
        ImageIO.write(image, "JPEG", out);
    }
}
2、然后写一个Controller
package com.jdwa.controller;

import com.jdwa.utill.VerifyCode;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;

@Controller
public class VerifyCodeController {

    @RequestMapping("code")
    public void getCode(HttpServletResponse response) throws IOException {
        VerifyCode vc = new VerifyCode();
        BufferedImage image = vc.getImage();
//        VerifyCode.veryfiCode = vc.getText();
        //实际项目中可以存到session中,
        // 如果无法维护session,也可以存一个静态变量,
        // 不过登录验证时(无论成功失败)要销毁上一次的验证码
        System.out.println(vc.getText());

        VerifyCode.output(image, response.getOutputStream());
    }
}

3、运行信息以及效果截图

技术图片
技术图片

二、centos7环境,Jersey框架的问题

1、当环境中没有代码中对应的字体,可能会导致获取不到image
yum install fontconfig  //安装字体库 
cd  /usr/share/fonts   //字体所在文件夹
mkdir chinese //新建文件夹,用于放中文字体文件。文件可在windows系统C:WindowsFonts下拷贝
chmod -R 755 /usr/share/fonts/chinese   //给字体文件赋权
fc-list  //查询当前支持的所有字体
2、获取不到HttpServletResponse,即使按照网上说的加上 @Context注解,安装较新版本,也未解决。如果有解决这个问题的大神,欢迎交流。
3、改用了struts2环境,顺利获取到
package *;

import *;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import static com.opensymphony.xwork2.Action.SUCCESS;

public class VerifyCodeAction implements ServletResponseAware {
    private static final Logger log = LoggerFactory.getLogger(VerifyCodeAction.class);
    private HttpServletResponse response;

    public String execute() {
        log.info("=============进入生成验证码方法================");
        ServletOutputStream out = null;
        try{
            VerifyCode vc = new VerifyCode();
            BufferedImage image = vc.getImage();
            log.info("=========image================= : {}",image.toString());
            out = response.getOutputStream();
            VerifyCode.output(image, out);
        }catch (Exception  ex) {
            log.error("=========生成验证码出错================= ");
        } finally {
            if (out != null){
                try {
                    out.close();
                } catch (IOException e){
                }
            }
        }
        return SUCCESS;
    }

    @Override
    public void setServletResponse(HttpServletResponse response) {
        this.response = response;
    }

}

实现刷新效果

<img src="vf.action" id="img" style="width: 75px; height:30px;">
<a href="#" onclick="changeVf()" style="display: block;">看不清</a>

js方法:

 function changeVf() {
        var doc = document.getElementById("img");
        var src = "vf.action?k=" + Math.random();
        doc.setAttribute("src",src);
    }

技术图片

路漫漫其修远兮,吾将上下而求索。。。


以上是关于验证码实现的主要内容,如果未能解决你的问题,请参考以下文章

JSP 设计教师与学生不同登陆界面(带验证码)

git动态验证码

代码实现PHP生成各种随机验证码

我的php代码中登陆界面加一个验证码,如何实现

爬虫遇到头疼的验证码?Python实战讲解弹窗处理和验证码识别

jquery实现手机发送验证码的倒计时代码