Java图片滑动验证码

目录

一、配置文件

二、图片

三、代码实现


前后端代码: 

java滚动验证码-前端和后端完整版_outdata的博客-CSDN博客_java图片滚动验证

图形滑动验证码JAVA实现【前后端结合】_LeonardoZzzz的博客-CSDN博客_滑动验证码完成安全验证

一、配置文件


#验证码图片地址,需要改成你本地的地址
#路径调试的时候,配成全路径,不要配成相对路径。相对路径打成jar包的时候,读取不到文件
#这是前后端分离方式的调用,路径应该由服务器来配置,这里需要手动配置路径。其它方式读取文件,可自行调整CaptchaServiceImpl实现类中selectSlideVerificationCode方法文件读取方式
captcha:
  slide-verification-code:
    path:
      template-image: "/static/templates"
      origin-image: "/static/targets"

二、图片

三、代码实现

import com.aliyun.oss.ServiceException;
import com.lgh.code.common.model.base.Result;
import com.lgh.universal.service.ImageVerificationService;
import com.lgh.universal.util.ImageVerificationCheckDTO;
import com.lgh.universal.util.ImageVerificationVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

/**
 * @author: cyl
 * @date: 2022/3/22 16:17
 */
@RestController
@RequestMapping(value = "/image/verification")
@Api(tags = "图片滑动验证码")
@Slf4j
@RequiredArgsConstructor
public class ImageVerificationController {

    private final ImageVerificationService service;


    @GetMapping("/get")
    @ApiOperation(value = "获取验证码")
    public Result getVerificationImage() {
        ImageVerificationVO vo;
        try {
            vo = service.selectSlideVerificationCode();
        } catch (ServiceException e) {
            return Result.fail(e.getMessage());
        }
        return Result.ok(vo);
    }


    @ApiOperation(value = "校验验证码")
    @PostMapping("/check")
    public Result checkVerificationResult(@Valid @RequestBody ImageVerificationCheckDTO dto) {
        return service.checkVerificationResult(dto.getX(), dto.getY());
    }

}
import com.aliyun.oss.ServiceException;
import com.lgh.code.common.constant.RedisConstants;
import com.lgh.code.common.constant.TokenTimeConstants;
import com.lgh.code.common.context.SecurityContextHolder;
import com.lgh.code.common.model.base.Result;
import com.lgh.code.redis.service.RedisService;
import com.lgh.universal.util.ImageRead;
import com.lgh.universal.util.ImageVerificationUtil;
import com.lgh.universal.util.ImageVerificationVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.util.Random;


/**
 * 图片滑动验证码 业务实现类
 * @author: cyl
 * @date: 2022/3/22 16:28
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ImageVerificationService {

    private final RedisService redisService;


    /**
     * 源图路径前缀
     */
    @Value("${captcha.slide-verification-code.path.origin-image:classpath:static/targets}")
    private String verificationImagePathPrefix;

    /**
     * 模板图路径前缀
     */
    @Value("${captcha.slide-verification-code.path.template-image:classpath:static/templates}")
    private String templateImagePathPrefix;

    /**
     * 获取滑动验证码
     *
     * @return 滑动验证码
     */
    public ImageVerificationVO selectSlideVerificationCode() throws ServiceException {

        ImageVerificationVO vo;
        try {

            //  随机取得原图文件夹中一张图片
            ImageRead originImageRead = readTargetImage();
            //  获取模板图片文件
            ImageRead templateImageRead = readTemplateImage(templateImagePathPrefix.concat("/template.png"));
            //  获取描边图片文件
            ImageRead borderImageRead = readBorderImageFile(templateImagePathPrefix.concat("/border.png"));

            //  获取原图文件类型
            String originImageFileType = originImageRead.getFileExtension();
            //  获取模板图文件类型
            String templateImageFileType = templateImageRead.getFileExtension();
            //  获取边框图文件类型
            String borderImageFileType = borderImageRead.getFileExtension();

            //  读取原图
            BufferedImage verificationImage = originImageRead.getImage();
            //  读取模板图
            BufferedImage readTemplateImage = templateImageRead.getImage();

            //  读取描边图片
            BufferedImage borderImage = borderImageRead.getImage();


            //  获取原图感兴趣区域坐标
            vo = ImageVerificationUtil.generateCutoutCoordinates(verificationImage, readTemplateImage);

            int y = vo.getY();
            redisService.set(RedisConstants.IMAGE_VERIFICATION + SecurityContextHolder.getUserId(), vo, TokenTimeConstants.MILLIS_MINUTES);

            //  根据原图生成遮罩图和切块图
            vo = ImageVerificationUtil.pictureTemplateCutout(verificationImage, originImageRead.getInputStream(), originImageFileType, readTemplateImage, templateImageFileType, vo.getX(), vo.getY());

            //   剪切图描边
            vo = ImageVerificationUtil.cutoutImageEdge(vo, borderImage, borderImageFileType);
            vo.setY(y);


            //  =============================================
            //  输出图片
//            HttpServletResponse response = getResponse();
//            response.setContentType("image/jpeg");
//            ServletOutputStream outputStream = response.getOutputStream();
//            outputStream.write(oriCopyImages);
//            BufferedImage bufferedImage = ImageIO.read(originImageFile);
//            ImageIO.write(bufferedImage, originImageType, outputStream);
//            outputStream.flush();
            //  =================================================

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }

        return vo;
    }

    /**
     * 读取目标图
     *
     * @return
     * @throws ServiceException
     */
    public ImageRead readTargetImage() throws ServiceException {
        ImageRead imageRead = null;

        try {
            Random random = new Random(System.currentTimeMillis());
            log.info("读取目标图: {}", verificationImagePathPrefix);
            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            Resource[] resources = resolver.getResources(verificationImagePathPrefix.concat("/*"));

            if (resources == null) {
                throw new RuntimeException("not found target image");
            }
            int i = random.nextInt(resources.length);
            imageRead = new ImageRead();
            imageRead.setImage(ImageIO.read(resources[i].getInputStream()));
            String extension = resources[i].getFilename().substring(resources[i].getFilename().lastIndexOf(".") + 1);
            imageRead.setInputStream(resources[i].getInputStream());
            imageRead.setFileExtension(extension);
            log.info("读取目标图: 完成");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
        return imageRead;
    }

    /**
     * 读取模板图
     *
     * @param path
     * @return
     * @throws ServiceException
     */
    public ImageRead readTemplateImage(String path) throws ServiceException {
        ImageRead templateImageFile = null;
        try {
            if (templateImageFile != null) {
                return templateImageFile;
            }
            templateImageFile = new ImageRead();
            log.info("读取模板图:{}", path);

            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            Resource resource = resolver.getResource(path);
            if (resource == null) {
                throw new RuntimeException("not found template image");
            }
            templateImageFile.setImage(ImageIO.read(resource.getInputStream()));
            String extension = resource.getFilename().substring(resource.getFilename().lastIndexOf(".") + 1);
            templateImageFile.setInputStream(resource.getInputStream());
            templateImageFile.setFileExtension(extension);
            log.info("读取模板图:完成");

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
        return templateImageFile;
    }

    /**
     * 读取边框图
     *
     * @param path
     * @return
     * @throws ServiceException
     */
    public ImageRead readBorderImageFile(String path) throws ServiceException {
        ImageRead borderImageFile = null;
        try {
            if (borderImageFile != null) {
                return borderImageFile;
            }
            borderImageFile = new ImageRead();
            log.info("读取边框图:{}", path);
            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            Resource resource = resolver.getResource(path);
            if (resource == null) {
                throw new RuntimeException("not found template image");
            }
            borderImageFile.setImage(ImageIO.read(resource.getInputStream()));
            String extension = resource.getFilename().substring(resource.getFilename().lastIndexOf(".") + 1);
            borderImageFile.setInputStream(resource.getInputStream());
            borderImageFile.setFileExtension(extension);
            log.info("读取边框图:完成");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
        return borderImageFile;
    }

    /**
     * 滑动验证码验证方法
     *
     * @param x x轴坐标
     * @param y y轴坐标
     * @return 滑动验证码验证状态
     * @throws ServiceException 验证滑动验证码异常
     */
    public Result checkVerificationResult(String x, String y) throws ServiceException {

        int threshold = 5;

        try {
            ImageVerificationVO vo = (ImageVerificationVO) redisService.get(RedisConstants.IMAGE_VERIFICATION + SecurityContextHolder.getUserId());
            if (vo != null) {
                if ((Math.abs(Integer.parseInt(x) - vo.getX()) <= threshold) && y.equals(String.valueOf(vo.getY()))) {
                    redisService.delete(RedisConstants.IMAGE_VERIFICATION + SecurityContextHolder.getUserId());
                    return Result.ok();
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
        return Result.fail("图片滑动验证失败");
    }


}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个简单的 Java 图片滑动验证码的示例代码,使用 Java Swing 库实现: ```java import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.Random; public class ImageSliderVerificationCode extends JFrame { private static final long serialVersionUID = 1L; private final int WIDTH = 400; private final int HEIGHT = 300; private final int BLOCK_SIZE = 50; private Image bgImage; private Image blockImage; private int blockX; private int blockY; private int mouseX; private int mouseY; private boolean isDragging; public ImageSliderVerificationCode() { setTitle("Image Slider Verification Code"); setSize(WIDTH, HEIGHT); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setResizable(false); setLocationRelativeTo(null); bgImage = new ImageIcon("background.jpg").getImage(); blockImage = new ImageIcon("block.png").getImage(); addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { if (e.getX() >= blockX && e.getX() <= blockX + BLOCK_SIZE && e.getY() >= blockY && e.getY() <= blockY + BLOCK_SIZE) { isDragging = true; mouseX = e.getX(); mouseY = e.getY(); } } public void mouseReleased(MouseEvent e) { isDragging = false; if (blockX >= WIDTH - BLOCK_SIZE) { JOptionPane.showMessageDialog(null, "Verification passed!"); System.exit(0); } else { blockX = 0; blockY = new Random().nextInt(HEIGHT - BLOCK_SIZE); repaint(); } } }); addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseEvent e) { if (isDragging) { blockX += e.getX() - mouseX; blockY += e.getY() - mouseY; if (blockX < 0) { blockX = 0; } if (blockX > WIDTH - BLOCK_SIZE) { blockX = WIDTH - BLOCK_SIZE; } if (blockY < 0) { blockY = 0; } if (blockY > HEIGHT - BLOCK_SIZE) { blockY = HEIGHT - BLOCK_SIZE; } mouseX = e.getX(); mouseY = e.getY(); repaint(); } } }); } public void paint(Graphics g) { g.drawImage(bgImage, 0, 0, null); g.drawImage(blockImage, blockX, blockY, null); } public static void main(String[] args) { ImageSliderVerificationCode verCode = new ImageSliderVerificationCode(); verCode.setVisible(true); } } ``` 此代码将生成一个包含背景图片和滑块图片的窗口。当用户按住滑块图片并拖动它时,窗口将显示移动后的滑块图片。如果用户将滑块图片拖动到窗口的右边缘,则显示验证通过的消息并退出程序。否则,滑块图片将被重置到窗口的左侧,并随机在窗口的垂直方向上移动。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值