滑块验证码后台生成及校验

目录

前言

思路流程

工具类代码

pom

抠图工具类

imageUtils

调用实现类


前言

在自己做的某一个项目中要求具备滑块验证码的功能,在翻阅部分博客后自己参考编写了一个后台的滑块验证码工具类,这里要给提供参考资料的博客说声谢谢,但是因时间久远忘记了之前的博客地址,所以也要说声抱歉。

思路流程

验证码的生成及验证流程是利用jhlabs jar包工具对图片进行抠图,将抠出的图片与背景图片通过base64编码转转成图片字符串发送给前台,并记录抠出图片的X坐标值,后续校验过程中我们会根据前台用户滑动的X坐标值与我们后台记录的X坐标值进行比较,在坐标值范围内则可证明验证成功。

注意点:

1.背景图使我们提前准备好的静态资源,图片像素大小为需均一致,并且前台编写时也要根据像素定义好验证码的长和高,这里默认设置了350X213像素的大小,后续更改图片大小也需要更改工具类中的宽和高。

2.在编译使用加载静态资源背景图时通过idea运行与直接运行jar包中的资源地址是不同的,这里我编写了jar包静态资源的加载函数,使用时可根据实际地址进行修改。

3.这里的验证码存储使用的是Ehcache,可根据自己的缓存技术修改存储。

工具类代码

pom

<dependency>
    <groupId>com.jhlabs</groupId>
    <artifactId>filters</artifactId>
    <version>2.0.235</version>
</dependency>
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.2.3</version>
</dependency>

抠图工具类



import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.resource.Resource;
import cn.hutool.core.util.NumberUtil;
import com.jhlabs.image.ImageUtils;
import com.jhlabs.image.InvertAlphaFilter;
import com.jhlabs.image.ShadowFilter;
import lombok.Data;

import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.geom.Arc2D;
import java.awt.geom.GeneralPath;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.util.Random;

/**
 * 滑块验证码
 *
 * @author hexm
 * @date 2020/10/23
 */
@Data
public class PuzzleCaptcha {
    /** 默认宽度,用来计算阴影基本长度 */
    private static final int DEFAULT_WIDTH = 350;
    /** 随机数 */
    private static final Random RANDOM = new Random();
    /** 蒙版 */
    private static Color color = new Color(255, 255, 255, 204);
    /** alpha通道过滤器 */
    private static InvertAlphaFilter alphaFilter = new InvertAlphaFilter();
    /** 边距 */
    private static int margin = 0;

    /** 生成图片的宽度 */
    private int width = DEFAULT_WIDTH;
    /** 生成图片高度 */
    private int height = 213;
    /** x轴的坐标,由算法决定 */
    private int x;
    /** y轴的坐标,由算法决定 */
    private int y;
    /** 拼图长宽 */
    private int vwh = 10 * 3;
    /** 原图 */
    private Image image;
    /** 大图 */
    private Image artwork;
    /** 小图 */
    private Image vacancy;
    /** 是否注重速度 */
    private boolean isFast = false;
    /** 小图描边颜色 */
    private Color vacancyBorderColor;
    /** 小图描边线条的宽度 */
    private float vacancyBorderWidth = 2.5f;
    /** 主图描边的颜色 */
    private Color artworkBorderColor;
    /** 主图描边线条的宽度 */
    private float artworkBorderWidth = 5f;
    /**
     * 最高放大倍数,合理的放大倍数可以使图像平滑且提高渲染速度
     * 当isFast为false时,此属性生效
     * 放大倍数越高,生成的图像越平滑,受原始图片大小的影响。
     */
    private double maxRatio = 2;
    /**
     * 画质
     *
     * @see Image#SCALE_DEFAULT
     * @see Image#SCALE_FAST
     * @see Image#SCALE_SMOOTH
     * @see Image#SCALE_REPLICATE
     * @see Image#SCALE_AREA_AVERAGING
     */
    private int imageQuality = Image.SCALE_SMOOTH;

    /**
     * 从文件中读取图片
     *
     * @param file
     */
    public PuzzleCaptcha(File file) {
        image = ImgUtil.read(file);
    }

    /**
     * 从文件中读取图片,请使用绝对路径,使用相对路径会相对于ClassPath
     *
     * @param imageFilePath
     */
    public PuzzleCaptcha(String imageFilePath) {
        image = ImgUtil.read(imageFilePath);
    }

    /**
     * 从{@link Resource}中读取图片
     *
     * @param resource
     */
    public PuzzleCaptcha(Resource resource) {
        image = ImgUtil.read(resource);
    }

    /**
     * 从流中读取图片
     *
     * @param imageStream
     */
    public PuzzleCaptcha(InputStream imageStream) {
        image = ImgUtil.read(imageStream);
    }

    /**
     * 从图片流中读取图片
     *
     * @param imageStream
     */
    public PuzzleCaptcha(ImageInputStream imageStream) {
        image = ImgUtil.read(imageStream);
    }

    /**
     * 加载图片
     *
     * @param image
     */
    public PuzzleCaptcha(Image image) {
        this.image = image;
    }

    /**
     * 加载图片
     *
     * @param bytes
     */
    public PuzzleCaptcha(byte[] bytes) {
        this.image = ImgUtil.read(new ByteArrayInputStream(bytes));
    }

    /**
     * 生成随机x、y坐标
     */
    private void init() {
        if (x == 0 || y == 0) {
            this.x = random(vwh, this.width - vwh - margin);
            this.y = random(margin, this.height - vwh - margin);
        }
    }

    /**
     * 执行
     */
    public void run() {
        init();
        // 缩略图
        Image thumbnail;
        GeneralPath path;
        int realW = image.getWidth(null);
        int realH = image.getHeight(null);
        int w = realW, h = realH;
        double wScale = 1, hScale = 1;
        // 如果原始图片比执行的图片还小,则先拉伸再裁剪
        boolean isFast = this.isFast || w < this.width || h < this.height;
        if (isFast) {
            // 缩放,使用平滑模式
            thumbnail = image.getScaledInstance(width, height, imageQuality);
            path = paintBrick(1, 1);
            w = this.width;
            h = this.height;
        } else {
            // 缩小到一定的宽高,保证裁剪的圆润
            boolean flag = false;
            if (realW > width * maxRatio) {
                // 不超过最大倍数且不超过原始图片的宽
                w = Math.min((int) (width * maxRatio), realW);
                flag = true;
            }
            if (realH > height * maxRatio) {
                h = Math.min((int) (height * maxRatio), realH);
                flag = true;
            }
            if (flag) {
                // 若放大倍数生效,则缩小图片至最高放大倍数,再进行裁剪
                thumbnail = image.getScaledInstance(w, h, imageQuality);
            } else {
                thumbnail = image;
            }
            hScale = NumberUtil.div(h, height);
  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值