欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

java HtmlUnit 模拟滑块验证 java 幻灯片验证码实现

最编程 2024-05-01 13:16:10
...


目录

一、配置文件

二、图片

三、代码实现


前后端代码: 

java滚动验证码-前端和后端完整版_outdata的博客-****博客_java图片滚动验证 图形滑动验证码JAVA实现【前后端结合】_LeonardoZzzz的博客-****博客_滑动验证码完成安全验证

一、配置文件


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


二、图片

java HtmlUnit 模拟滑块验证 java滑动验证码实现_java


java HtmlUnit 模拟滑块验证 java滑动验证码实现_Image_02


java HtmlUnit 模拟滑块验证 java滑动验证码实现_java_03


java HtmlUnit 模拟滑块验证 java滑动验证码实现_验证码_04


三、代码实现


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("图片滑动验证失败");
    }


}


推荐阅读