栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Java

生成图片中验证码

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

生成图片中验证码

一、预览结果

生成如下的验证码

有两种工具生成验证码:Captcha 和 kaptcha

二、Captcha验证码的代码 2.1 pom

  com.ramostear
  Happy-Captcha
  1.0.1


2.2 生成验证码

只需要添加一行代码即可生成验证码图片,request和response是必须提供的参数。
NUMBER 数字
CHINESE 中文
DEFAULT 数字加英文
WORD 英文
ARITHMETIC 计算

@GetMapping("/captcha")
@ApiOperation(value = "登录模块生成验证码接口")
public void happyCaptcha(HttpServletRequest request, HttpServletResponse response){
    System.out.println("======生成一次验证码======");
    HappyCaptcha.require(request,response).type(CaptchaType.NUMBER).build().finish();
}

2.3 校验验证码

对验证码进行的校验也是十分简单,也只需要几行代码就可解决。

@PostMapping("/verify")
public String verify(String code,HttpServletRequest request){
    //Verification Captcha
    boolean flag = HappyCaptcha.verification(request,code,true);
    if(flag){
        // 校验通过
    }
}

2.4 清理验证码

当验证码被使用后,可以通过HappyCaptcha类种的remove()方法将Session中存放的验证码清理掉,避免出现一次验证码多次使用的情况。

@GetMapping("/remove/captcha")
public void removeCaptcha(HttpServletRequest request){
    HappyCaptcha.remove(request);   
}

三、kaptcha验证码的代码 3.1 pom


            com.github.penggle
            kaptcha
            2.3.2
        
3.2 配置类
package com.example.demo001.config;

import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;


@Configuration
public class KaptchaConfig {
    @Bean
    public DefaultKaptcha getDefaultKaptcha() {
        DefaultKaptcha defaultKaptcha=new DefaultKaptcha();
        Properties properties=new Properties();
        //是否有边框
        properties.setProperty(Constants.KAPTCHA_BORDER,"yes");
        //验证码文本颜色
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR,"blue");
        //验证码图片宽度
        properties.setProperty(Constants.KAPTCHA_IMAGE_WIDTH,"160");
        //验证码图片高度
        properties.setProperty(Constants.KAPTCHA_IMAGE_HEIGHT,"60");
        //文本字符大小
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE,"38");
        //验证码session的值
        properties.setProperty(Constants.KAPTCHA_SESSION_CONFIG_KEY,"kaptchaCode");
        //验证码文本长度
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH,"4");
        //字体
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_NAMES, "宋体,楷体,微软雅黑");

        Config config = new Config(properties);
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
}

3.3 生成验证码
@Resource
    private Producer kaptchaProducer;

    @GetMapping("verifyCode")
    public void createVerifyCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //响应立即过期
        response.setDateHeader("Expires", 0);
        //不缓存任何图片数据
        response.setHeader("Cache-Control", "no-store,no-cache,must-revalidate");
        response.setHeader("Cache-Control", "post-check=0,pre-check=0");
        response.setHeader("Pragma", "no-cache");
        response.setContentType("image/png");
        //生成验证码字符文本
        String verifyCode = kaptchaProducer.createText();
        request.getSession().setAttribute("kaptchaVerifyCode", verifyCode);
        System.out.println(request.getSession().getAttribute("kaptchaVerifyCode"));
        BufferedImage image = kaptchaProducer.createImage(verifyCode);//创建验证图片
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(image, "png", out);
        //输出和关闭输出
        out.flush();
        out.close();
    }

3.4 校验验证码
	public static boolean validate(String registerCode) {
		// 获取Session中验证码
		Object captcha = ServletUtils.getAttribute(Constants.KAPTCHA_SESSION_KEY);
		// 判断验证码是否为空
		if (StringUtils.isEmpty(registerCode)) {
			return false;
		}
		// 校验验证码的正确与否
		boolean result = registerCode.equalsIgnoreCase(captcha.toString());
		if (result) {
			// 正确了后,将验证码从session中删掉
			ServletUtils.getRequest().getSession().removeAttribute(Constants.KAPTCHA_SESSION_KEY);
		}
		// 返回验证结果
		return result;
	}

四、点击验证码的代码

4.1 验证码实体类
 
 
 
import java.io.Serializable;
 
public class AnchorPoint implements Serializable {
 
    private static final long serialVersionUID = 2L;
 
 
    
    private Integer x_iv = 26;
    
    private Integer y_iv = 21;
 
    private Integer x;
    private Integer y;
 
    public AnchorPoint(){
        this.x = 0;
        this.y = 0;
    }
 
 
    public AnchorPoint(Integer x, Integer y){
        this.x = x;
        this.y = y;
    }
 
    public Integer getX() {
        return x;
    }
 
 
    public Integer getY() {
        return y;
    }
 
    public void setX(Integer x) {
        this.x = x;
    }
 
    public void setY(Integer y) {
        this.y = y;
    }
 
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        AnchorPoint that = (AnchorPoint) o;
 
        //当X位置小于偏移量进行判段Y轴的偏移量
        if(this.x+this.x_iv > that.getX() || this.x - this.x_iv < that.getX()){
            //当Y轴的偏移量符合安全距离 判断锚点有效
            if(this.y+this.y_iv < that.getY() || this.y-this.y_iv > that.getY()){
                return false;
            }
        }else{
            //两个对象的X点保持在偏移量之外无需比较Y轴位置,判定锚点有效
            return false;
        }
 
 
        return true;
 
    }
 
    @Override
    public int hashCode() {
        return 1;
    }
 
    @Override
    public String toString() {
        return "AnchorPoint{" +
                "x=" + x +
                ", y=" + y +
                '}';
    }
}
4.2 图片生成工具类实现
 
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.*;
 

public class DrawCaptchaUtil {
 
    
    private static int canvasWidth = 300;
 
    
    private static int canvasHeight = 150;
 
 
    
    private static int imgWidth = 300;
 
    
    private static int imgHeight = 150;
 
    
    private static int charNumber = 5;
 
    
    private static int fontSize = 18;
    
    private static int charImgWidth = 20;
    
    private static int charImgHeight = 25;
 
 
 
    
    public static BufferedImage drawImg(LinkedHashMap checkCode,String bkDirPath) throws IOException {
 
        BufferedImage imgCanvas = new BufferedImage(canvasWidth, canvasHeight, BufferedImage.TYPE_INT_BGR);
        Graphics graphics = imgCanvas.getGraphics();
 
 
        //绘制图形
//        graphics.setColor(new Color(0,0,0,0));
        graphics.fillRect(0,0,imgWidth,imgHeight);
 
        File bkPath = randomBackGroundImage(bkDirPath);
 
        BufferedImage read = ImageIO.read(Files.newInputStream(Paths.get(bkPath.getAbsolutePath())));
        graphics.drawImage(read,0,0,null,null);
        //绘制字体
//        graphics.setColor(getRandomColor());
        //随机在图片中生成5个绘制点每个绘制点半径能不能重叠
        Set point = new HashSet<>();
 
        addPoint(point);
        Object[] pointArr = point.toArray();
        List charList = new ArrayList<>();
        for (int i = 0; i < charNumber; i++) {
            AnchorPoint p = (AnchorPoint)pointArr[i];
            graphics.drawImage(getCharImg(getRandomColor(),charList),p.getX(),p.getY(),null,null);
 
        }
        //随机获取3个字符串作为校验对象
        Object[] charArr = charList.toArray();
        Random random = new Random();
        for (int i = 0; i < 3; i++) {
            int num = random.nextInt(pointArr.length-i);
            String key = (String) charArr[num];
            AnchorPoint value = (AnchorPoint) pointArr[num];
            checkCode.put(key,value);
            //置换位置
            Object a = pointArr[num];
            pointArr[num] = pointArr[pointArr.length - 1 - i];
            pointArr[pointArr.length - 1 - i] = a;
 
            a = charArr[num];
            charArr[num] = charArr[charArr.length - 1 -  i];
            charArr[charArr.length - 1 - i] = a;
        }
 
        return imgCanvas;
    }
 
    
    private static File randomBackGroundImage(String dir){
        File file = new File(dir);
        if(file.isDirectory()){
            File[] files = file.listFiles();
            Random random = new Random();
            int i = random.nextInt(files.length);
            return files[i];
        }else{
            return file;
        }
    }
 
    
    private static void addPoint(Set point){
        Random random = new Random();
        //避免因为坐标点过于特殊导致无法获取下一个坐标点进入死循环,到100置空重新获取
        int clearNumber = 0;
        //生成前2个点坐标
        while (point.size() < 2){
 
            //添加X坐标点
            point.add(new AnchorPoint(random.nextInt(canvasWidth/3),random.nextInt(canvasHeight-charImgWidth)));
            if(clearNumber == 100){
                point.clear();
                clearNumber = 0;
            }
            clearNumber++;
 
        }
        clearNumber = 0;
        //生成后3个点坐标
        while (point.size() < charNumber){
            //添加X坐标点
            point.add(new AnchorPoint(random.nextInt(canvasWidth-charImgWidth),random.nextInt(canvasHeight-charImgHeight)));
            if(clearNumber == 100){
                point.clear();
                clearNumber = 0;
                addPoint(point);
                break;
            }
            clearNumber++;
        }
 
 
 
 
    }
 
    
    private static BufferedImage getCharImg(Color fontColor, List charList) throws UnsupportedEncodingException {
        BufferedImage fillRect = new BufferedImage(charImgWidth, charImgHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = fillRect.createGraphics();
        g.setColor(new Color(0,0,0,0));
        g.fillRect(0,0,charImgWidth,charImgHeight);
        g.setColor(fontColor);
        Font font = new Font("微软雅黑", Font.BOLD, fontSize);
        AffineTransform affineTransform = new AffineTransform();
        affineTransform.rotate(Math.toRadians(30),0,0);
        font.deriveFont(affineTransform);
        g.setFont(font);
        String charStr = getChineseCharacters();
        charList.add(charStr);
        g.drawString(charStr,0,charImgHeight-5);
        g.dispose();
        return fillRect;
    }
 
    
    private static Color getRandomColor(){
        Random random = new Random();
        return new Color(
                random.nextInt(255),
                random.nextInt(255),
                random.nextInt(255));
 
    }
 
    
    private static String getChineseCharacters() throws UnsupportedEncodingException {
        Integer hightPos, lowPos; // 定义高低位
        Random random = new Random();
        hightPos = (176 + Math.abs(random.nextInt(39)));
        lowPos = (161 + Math.abs(random.nextInt(93)));
        byte[] bytes = new byte[2];
        bytes[0] = hightPos.byteValue();
        bytes[1] =lowPos.byteValue();
        return new String(bytes,"GBK");
 
    }
 
 
 
 
}
五、滑动拼图验证码

转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1039465.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号