获取动态拖动码

使用java自带的awt

DragVerifyCodeUtils 工具类

package com.meeno.common.cerifycode;

import cn.hutool.core.codec.Base64;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Map;
import java.util.Random;

/**
 * @Author: wzq
 * @Date: Created in 2020/9/23
 * @Description: 图片拖动工具类
 */
@Slf4j
public class DragVerifyCodeUtils {

    static int targetWidth = 55;//小图长
    static int targetHeight = 45;//小图宽
    static int circleR = 8;//半径
    static int r1 = 4;//距离点

    /**
     * @Createdate: 2019年1月24日上午10:52:42
     * @Title: getBlockData
     * @Description: 生成小图轮廓
     * @author zhoujin
     * @return int[][]
     * @throws
     */
    private static int[][] getBlockData() {
        int[][] data = new int[targetWidth][targetHeight];
        double x2 = targetWidth -circleR; //47

        //随机生成圆的位置
        double h1 = circleR + Math.random() * (targetWidth-3*circleR-r1);
        double po = Math.pow(circleR,2); //64

        double xbegin = targetWidth - circleR - r1;
        double ybegin = targetHeight- circleR - r1;

        //圆的标准方程 (x-a)²+(y-b)²=r²,标识圆心(a,b),半径为r的圆
        //计算需要的小图轮廓,用二维数组来表示,二维数组有两张值,0和1,其中0表示没有颜色,1有颜色
        for (int i = 0; i < targetWidth; i++) {
            for (int j = 0; j < targetHeight; j++) {
                double d2 = Math.pow(j - 2,2) + Math.pow(i - h1,2);
                double d3 = Math.pow(i - x2,2) + Math.pow(j - h1,2);
                if ((j <= ybegin && d2 < po)||(i >= xbegin && d3 > po)) {
                    data[i][j] = 0;
                }  else {
                    data[i][j] = 1;
                }
            }
        }
        return data;
    }

    /**
     *
     * @Createdate: 2019年1月24日上午10:51:30
     * @Title: cutByTemplate
     * @Description: 有这个轮廓后就可以依据这个二维数组的值来判定抠图并在原图上抠图位置处加阴影,
     * @author zhoujin
     * @param oriImage  原图
     * @param targetImage  抠图拼图
     * @param templateImage 颜色
     * @param x
     * @param y void
     * @throws
     */
    private static void cutByTemplate(BufferedImage oriImage, BufferedImage targetImage, int[][] templateImage, int x, int y){
        int[][] martrix = new int[3][3];
        int[] values = new int[9];
        //创建shape区域
        for (int i = 0; i < targetWidth; i++) {
            for (int j = 0; j < targetHeight; j++) {
                int rgb = templateImage[i][j];
                // 原图中对应位置变色处理
                int rgb_ori = oriImage.getRGB(x + i, y + j);

                if (rgb == 1) {
                    targetImage.setRGB(i, j, rgb_ori);

                    //抠图区域高斯模糊
                    readPixel(oriImage, x + i, y + j, values);
                    fillMatrix(martrix, values);
                    oriImage.setRGB(x + i, y + j, avgMatrix(martrix));
                }else{
                    //这里把背景设为透明
                    targetImage.setRGB(i, j, rgb_ori & 0x00ffffff);
                }
            }
        }
    }


    private static void readPixel(BufferedImage img, int x, int y, int[] pixels) {
        int xStart = x - 1;
        int yStart = y - 1;
        int current = 0;
        for (int i = xStart; i < 3 + xStart; i++)
            for (int j = yStart; j < 3 + yStart; j++) {
                int tx = i;
                if (tx < 0) {
                    tx = -tx;

                } else if (tx >= img.getWidth()) {
                    tx = x;
                }
                int ty = j;
                if (ty < 0) {
                    ty = -ty;
                } else if (ty >= img.getHeight()) {
                    ty = y;
                }
                pixels[current++] = img.getRGB(tx, ty);

            }
    }

    private static void fillMatrix(int[][] matrix, int[] values) {
        int filled = 0;
        for (int i = 0; i < matrix.length; i++) {
            int[] x = matrix[i];
            for (int j = 0; j < x.length; j++) {
                x[j] = values[filled++];
            }
        }
    }

    private static int avgMatrix(int[][] matrix) {
        int r = 0;
        int g = 0;
        int b = 0;
        for (int i = 0; i < matrix.length; i++) {
            int[] x = matrix[i];
            for (int j = 0; j < x.length; j++) {
                if (j == 1) {
                    continue;
                }
                Color c = new Color(x[j]);
                r += c.getRed();
                g += c.getGreen();
                b += c.getBlue();
            }
        }
        return new Color(r / 8, g / 8, b / 8).getRGB();
    }

    /**
     * @return Map<String, Object>  返回生成的抠图和带抠图阴影的大图 base64码及抠图坐标
     * @Description: 读取网络图片,生成拼图验证码
     * @author zhoujin
     */
    public static Map<String, Object> createImage(String imgUrl, Map<String, Object> resultMap) {
        try {
            //通过URL 读取图片
            URL url = new URL(imgUrl);
            BufferedImage bufferedImage = ImageIO.read(url.openStream());
            Random rand = new Random();
            int widthRandom = rand.nextInt(bufferedImage.getWidth() - targetWidth - 100 + 1) + 100;
            int heightRandom = rand.nextInt(bufferedImage.getHeight() - targetHeight + 1);
            log.info("原图大小{} x {},随机生成的坐标 X,Y 为({},{})", bufferedImage.getWidth(), bufferedImage.getHeight(), widthRandom, heightRandom);

            BufferedImage target = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_4BYTE_ABGR);
            //输出裁剪后的图片
            ImageIO.write(target, "jpg", new FileOutputStream("D:\\work\\temp\\cuttingImage.jpg"));

            cutByTemplate(bufferedImage, target, getBlockData(), widthRandom, heightRandom);
            resultMap.put("bigImage", getImageBASE64(bufferedImage));//大图
            resultMap.put("smallImage", getImageBASE64(target));//小图
            resultMap.put("xWidth", widthRandom);
            resultMap.put("yHeight", heightRandom);

            log.info("-----");
            log.info(getImageBASE64(target));

            //输出原图
            ImageIO.write(bufferedImage, "jpg", new FileOutputStream("D:\\work\\temp\\img.jpg"));
        } catch (Exception e) {
            log.info("创建图形验证码异常", e);
        } finally {
            return resultMap;
        }
    }

    private static String  getImageBASE64(BufferedImage image) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write(image, "png", out);
        byte[] bytes = out.toByteArray();

        String str = Base64.encode(bytes);
        str = "data:image/jpg;base64," + str;

        return str;
    }

}

获取动态拖动码

/**
     * 获取动态拖动码
     * @return
     */
    @RequestMapping("getDragVerifyCode.action")
    public ResponseBean getDragVerifyCode() {
        //图库地址 定制 宽 300 高 200的图片
        String path = "https://picsum.photos/300/200";

        Map<String, Object> resultMap = new HashMap<>();
        DragVerifyCodeUtils.createImage(path, resultMap);

        //save redis
        String uuid = IdUtil.simpleUUID();
        String key = "RandomVerify:" + uuid;
        RedisUtil.set(key, resultMap, 180);

        resultMap.put("uuid", uuid);
        return ResultUtil.success(resultMap);
    }

校验

/**
     * 账号登录
     * @param session
     * @param phone
     * @param pwd
     * @param entryType
     * @return
     */
    @RequestMapping("accountLogin.do")
    public ResponseBean accountLogin(final HttpSession session, String phone, String pwd, String entryType,
                                     String uuid, Double targetX){

        //校验验证码
        MeenoAssert.notNull(targetX,"targetX can not empty!");
        MeenoAssert.hasLength(uuid, "uuid can not empty!");
        Object randomVerifyObj = RedisUtil.get("RandomVerify:" + uuid);

        //删除验证码
        RedisUtil.del("RandomVerify:" + uuid);

        MeenoAssert.notNull(randomVerifyObj, CErrEnum.RANDOM_VERIFY_CODE_FAILURE);

        Map<String, Object> randomVerifyCodeMap = (Map<String, Object>) randomVerifyObj;
        Object xWidth = randomVerifyCodeMap.get("xWidth");
        double x = Double.parseDouble(xWidth.toString());

        MeenoAssert.notTrue(Math.abs(x - targetX) > 10,CErrEnum.RANDOM_VERIFY_ERR);

        /*MeenoAssert.notNull(randomCerifyCodeObj, CErrEnum.RANDOM_VERIFY_CODE_FAILURE);
        MeenoAssert.isTrue(randomCerifyCode.toLowerCase().equals(randomCerifyCodeObj.toString().toLowerCase()), CErrEnum.RANDOM_VERIFY_CODE_ERR);*/


        LoginResult loginResult = this.employeeService.accountLogin(session, phone, pwd, entryType);
        EmpView employeeView = this.employeeService.getEmployee(loginResult.getUserInfo().getId());

        Map<String,Object> resultMap = Maps.newHashMap();
        resultMap.put("loginResult", loginResult);
        resultMap.put("employee", employeeView);

        return ResultUtil.success(resultMap);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值