效果:

1、环境

jdk1.8 springboot 2.7  vue

2、验证码图片生成类

package my.verify.slide.utils;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;import static java.awt.Color.BLACK;
import static java.awt.Transparency.TRANSLUCENT;/*** 验证码绘制类*/
public class DrawCaptchaUtil {/*** 画布宽度*/private static int canvasWidth = 300;/*** 画布高度*/private static int canvasHeight = 150;/*** 图片宽度*/private static int imageWidth = 300;/*** 图片高度*/private static int imageHeight = 150;/*** 滑块画布宽度*/private static int slideCanvasWidth = 50;/*** 滑块画布高度*/private static int slideCanvasHeight = 150;/*** 滑块图片宽度*/private static int slideImageWidth = 50;/*** 滑块图片高度*/private static int slideImageHeight = 50;/*** 绘制背景图片** @param imagePath      图片路径* @param slideImagePath 滑块图片路径* @param code 存放验证码信息* @return* @throws IOException*/public static Map<String, String> drawImage(File imagePath, File slideImagePath,HashMap<String,Integer> code) throws IOException {BufferedImage canvas = new BufferedImage(canvasWidth, canvasHeight, BufferedImage.TYPE_INT_ARGB);Graphics2D g = (Graphics2D) canvas.getGraphics();g.fillRect(0, 0, imageWidth, imageHeight);BufferedImage read = ImageIO.read(Files.newInputStream(Paths.get(imagePath.getAbsolutePath())));g.drawImage(read, 0, 0, null, null);int[] point = randomAnchorPoint();//绘制滑块图片BufferedImage slideImage = drawSlideImage(slideImagePath, canvas, point[0], point[1]);//设置为透明覆盖 很重要g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.9f));//覆盖阴影g.drawImage(drawSlideImageShadow(slideImagePath), point[0], point[1], null, null);g.dispose();HashMap<String, String> images = new HashMap<>();images.put("bkImage", ImageToBase64Util.bufferedImageToBase64(canvas));images.put("slideImage", ImageToBase64Util.bufferedImageToBase64(slideImage));//存放验证码code.put("offset",point[0]);return images;}/*** 绘制滑块** @param slideImagePath 滑块图片路径* @param bkImg          验证码背景图* @param x              随机坐标X* @param y              随机坐标Y* @return* @throws IOException*/private static BufferedImage drawSlideImage(File slideImagePath, BufferedImage bkImg, int x, int y) throws IOException {BufferedImage canvas = new BufferedImage(slideCanvasWidth, slideCanvasHeight, BufferedImage.TYPE_INT_ARGB);Graphics2D g = canvas.createGraphics();g.getDeviceConfiguration().createCompatibleImage(slideCanvasWidth, slideCanvasHeight, Transparency.TRANSLUCENT);g = canvas.createGraphics();BufferedImage slideImage = bkImg.getSubimage(x, y, slideImageWidth, slideImageHeight);BufferedImage slide = ImageIO.read(Files.newInputStream(Paths.get(slideImagePath.getAbsolutePath())));Graphics2D g2 = slide.createGraphics();//设置为透明覆盖 很重要g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1.0f));g2.drawImage(slideImage, 0, 0, null);g2.dispose();g.drawImage(slide, 0, y, null);g.dispose();return canvas;}/*** 绘制背景图上的阴影** @param slideImagePath* @return* @throws IOException*/private static BufferedImage drawSlideImageShadow(File slideImagePath) throws IOException {BufferedImage slide = ImageIO.read(Files.newInputStream(Paths.get(slideImagePath.getAbsolutePath())));return slide;}/*** 生成随机坐标点 x > 滑块画布宽度 y < 滑块画布高度-滑块图片高度** @return*/private static int[] randomAnchorPoint() {Random random = new Random();//设置x坐标从 slideCanvasWidth 开始至 canvasWidth - slideCanvasWidth 范围随机int x = random.nextInt(canvasWidth - slideImageWidth);if (x < slideImageWidth) {//随机生成x点小于图片宽度+上图片宽度x += slideCanvasWidth;}//设置y坐标int y = random.nextInt(canvasHeight - slideImageHeight);int[] point = {x, y};return point;}}

3、BufferedImage转BASE64类

package my.verify.slide.utils;import sun.misc.BASE64Encoder;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;public class ImageToBase64Util {/*** BufferedImage 对象转BASE64* @param image* @return*/public static String bufferedImageToBase64(BufferedImage image)  {ByteArrayOutputStream out = new ByteArrayOutputStream();try {ImageIO.write(image,"PNG",out);byte[] bytes = out.toByteArray();BASE64Encoder base64Encoder = new BASE64Encoder();return base64Encoder.encodeBuffer(bytes);} catch (IOException e) {try {if(out != null){out.close();}} catch (IOException ex) {}}return null;}}

4、前端实现

<template><div class="image-body"><div class="image-div"><ElImage class="image-bk" :src="bkImage"></ElImage><ElImage:style="{ marginLeft: marginLeft + 'px' }"class="image-slide":src="slideImage"></ElImage></div><div class="image-slide-div"><div class="image-slide-text"><span class="image-slide-tips">{{ showTips ? "向右拖动滑块填充拼图" : "&nbsp;" }}</span></div><div :style="slideStyle" class="slide-div"><ElButton:style="slideButtonStyle"@mousedown="handleDrag"class="slide-button":round="false"type="primary"plain><template #icon><Right v-if="result === 'default'" /><Check v-if="result === 'success'" /><Close v-if="result === 'error'" /></template></ElButton></div></div></div>
</template>
<script lang="ts">
import { defineComponent, onMounted, ref, computed, reactive } from "vue";
import { getSlideImage, verifyCodeCheck } from "@/assets/api/api";
import { ElImage, ElIcon, ElButton } from "element-plus";
import { Right, Check, Close } from "@element-plus/icons-vue";
export default defineComponent({components: { ElImage, ElIcon, Right, Check, Close, ElButton },setup() {//验证码背景图片const bkImage = ref("");//验证码滑块图片const slideImage = ref("");//是否显示提示文字const showTips = ref(true);//验证码滑块图片移动量const marginLeft: any = ref(0);//验证码状态const result: any = ref("default");//滑动背景样式let slideStyleJson: any = reactive({});//滑块按钮样式let slideButtonStyleJson: any = reactive({});const slideStyle = computed(() => {return slideStyleJson;});const slideButtonStyle = computed(() => {return slideButtonStyleJson;});function loadImage() {getSlideImage().then((res: any) => {bkImage.value = "data:image/png;base64," + res.bkImage;slideImage.value = "data:image/png;base64," + res.slideImage;});}/*** 改变拖动时改变*/function dragChangeSildeStyle() {slideStyleJson.background = "rgba(25,145,250,0.5)";slideStyleJson.transition = null;slideButtonStyleJson.transition = null;}/*** 验证成功*/function handleSuccess() {result.value = "success";slideStyleJson.background = "#d2f4ef";slideButtonStyleJson["background"] = "#52ccba";slideButtonStyleJson["color"] = "white";slideButtonStyleJson["border"] = "1px solid #52ccba";}/*** 验证失败*/function handleError() {result.value = "error";slideStyleJson.background = "rgba(245,122,122,0.5)";slideButtonStyleJson["background"] = "#f57a7a";slideButtonStyleJson["color"] = "white";slideButtonStyleJson["border"] = "1px solid #f57a7a";setTimeout(() => {handleReset();}, 300);}/*** 重置验证码*/function handleReset() {result.value = "default";marginLeft.value = 0;slideStyleJson.width = "0px";slideButtonStyleJson.marginLeft = "0px";slideButtonStyleJson.color = null;slideButtonStyleJson.border = null;slideButtonStyleJson.background = null;slideStyleJson.transition = "width 0.5s";slideButtonStyleJson.transition = "margin-left 0.5s";showTips.value = true;loadImage();}onMounted(() => {loadImage();});//添加移动事件function handleDrag(c: any) {let clickX = c.clientX;dragChangeSildeStyle();showTips.value = false;document.onmousemove = function (e: any) {let moveX = e.clientX;let offset: any = moveX - clickX;if (offset < 0) {offset = 0;} else if (offset > 250) {offset = 250;}let slidePadding: any = (offset / 25).toFixed(0);let slideDivOffset = offset + parseInt(slidePadding) + "px";slideStyleJson.width = slideDivOffset;slideButtonStyleJson.marginLeft = slideDivOffset;marginLeft.value = offset;};document.onmouseup = async function () {document.onmousemove = null;document.onmouseup = null;//校验验证码const res:any = await verifyCodeCheck({ offset: marginLeft.value });if (res) {//成功handleSuccess();} else {//失败handleError();}};}return {loadImage,bkImage,slideImage,marginLeft,Right,Close,Check,handleDrag,slideStyle,slideButtonStyle,result,showTips,};},
});
</script>
<style lang="less" scoped>
.image-body {margin: 0 auto;width: 300px;.image-div {width: 300px;height: 150px;background: rgb(153, 216, 197);.image-bk {width: 300px;height: 150px;z-index: 1;position: absolute;}.image-slide {width: 50px;height: 150px;position: absolute;z-index: 2;}}.image-slide-div {width: 300px;height: 38px;margin-top: 15px;position: relative;.image-slide-text {background: #f7f9fa;border: 1px solid #ebebeb;.image-slide-tips {font-size: 14px;line-height: 38px;text-align: center;}}.slide-div {width: 0px;height: 38px;margin-top: -39px;.slide-button {width: 40px;height: 38px;border: none;border-left: 1px solid;border-right: 1px solid;border-color: #ebebeb;background: white;cursor: pointer;&:hover {background: #1991fa;border-color: #1991fa;color: white;}}}}
}
</style>

源码链接:前端GitHub - fleeEarth/slide_view

后端GitHub - fleeEarth/slide: 滑动拼图验证码

Java+vue实现滑动拼图验证码简单实现相关推荐

  1. uniapp、vue实现滑动拼图验证码

    实际开发工作中,在登陆的时候需要短信验证码,但容易引起爬虫行为,需要用到反爬虫验证码,今天介绍一下拼图验证码,解决验证码反爬虫中的滑动验证码反爬虫. 原理 滑动拼图验证码是在滑块验证码的基础上增加了一 ...

  2. 滑动拼图验证码操作步骤:_拼图项目:一个不完整的难题

    滑动拼图验证码操作步骤: 马克·雷因霍尔德(Mark Reinhold)最近提议延迟Java 9,以花更多的时间完成项目Jigsaw,这是即将发布的版本的主要功能. 虽然这个决定肯定会使Java的厄运 ...

  3. 滑动拼图验证码操作步骤:_拼图项目:延期的后果

    滑动拼图验证码操作步骤: Mark Reinhold先生于2012年7月宣布 ,他们计划从Java 8撤消Jigsaw项目 ,因为Jigsaw计划于2013年9月(从现在开始一年)推迟其发布. 这个日 ...

  4. html 滑动拼图验证,vue登录滑动拼图验证

    vue登录滑动拼图验证 vue登录滑动拼图验证 一.安装插件: npm install --save vue-monoplasty-slide-verify 二.main.js引入: import S ...

  5. js php滑动拼图解锁,js 滑动拼图验证码

    以前的验证码很简单,就是一个带些背景色或背景图和干扰线的纯数字字母类的验证码,现在已经发展变得很丰富了.我见过的就有好几种:纯字母数字类,数学计算类,依次点击图片上的文字类,从下列图片列表里选取符合描 ...

  6. 滑动拼图验证码 免费 java_js+canvas实现滑动拼图验证码功能

    上图为网易云盾的滑动拼图验证码,其应该有一个专门的图片库,裁剪的位置是固定的.我的想法是,随机生成图片,随机生成位置,再用canvas裁剪出滑块和背景图.下面介绍具体步骤. 首先随便找一张图片渲染到c ...

  7. Android 滑动拼图验证码控件

    Android 滑动拼图验证码控件 简介: 很多软件为了安全防止恶意攻击,会在登录/注册时进行人机验证,常见的人机验证方式有:谷歌点击复选框进行验证,输入验证码验证,短信验证码,语音验证,文字按顺序选 ...

  8. 小视频app源码,Android 滑动拼图验证码控件

    小视频app源码,Android 滑动拼图验证码控件 代码实现: 滑块视图类:SlideImageView.java.实现小视频APP源码随机选取拼图位置,对拼图位置进行验证等功能. public c ...

  9. php滑动拼图验证,JS怎么实现滑动拼图验证码

    这次给大家带来JS怎么实现滑动拼图验证码,JS实现滑动拼图验证码的注意事项有哪些,下面就是实战案例,一起来看一下. 上图为网易云盾的滑动拼图验证码,其应该有一个专门的图片库,裁剪的位置是固定的.我的想 ...

  10. 爬虫之极验验证码破解-滑动拼图验证码破解

    滑动拼图验证码破解 前言 步骤分析 第一步,获取原图 第二步 拼接图片 第三步 计算豁口所在位置 第四步 计算拖动距离 模拟拖动 其他 前言 滑动验证码已经流行很多年了,我们在这里尝试一下如何实现滑动 ...

最新文章

  1. ZOJ 1970 All in All
  2. 我的技术回顾那些与ABP框架有关的故事-2017年
  3. 三、Web服务器——HTTP协议 Response对象 ServletContext对象 学习笔记
  4. Android安全笔记-Tasks与Recents Screen与Fragment基本概念
  5. 代码组织和部署 文件操作 node.js 1
  6. 构建高性能.NET应用之配置高可用IIS服务器-第五篇 IIS常见问题之:工作进程回收机制(中)...
  7. 360html5播放加速,总结:没有讨论加速问题,“视频快速观看”完全支持360种浏览器...
  8. Axure中引入Echarts图表并制作元件库
  9. Windows + CUDA + Anaconda + TensorFlow + PyCharm
  10. 数学 二维向量(加法、减法、模、点乘、叉乘)
  11. Mac系统空格预览放大图片
  12. python深度学习include框架_《用Python实现深度学习框架》上市
  13. js原生后代选择器_jQuery的后代选择器ancestor descendant介绍和示例解析
  14. 如何查看一个vs工程使用的vs版本是哪一个?
  15. html页分割线最简单的实现方式
  16. Coder HDU - 4288
  17. CAD中如何旋转图片
  18. MATLAB轻松绘制地图路线——已知及未知坐标下的处理方法(1)
  19. Genessential获近千万元天使轮融资,明年推出AGEs 手持检测设备...
  20. 8.1 幽灵(no.1~no.10)

热门文章

  1. 阿里海量大数据平台的运维智能化实践
  2. 通达oa mysql密码_谁知道通达OA数据库user表密码的加密方法?
  3. CentOS 7安装TeamView
  4. cad快捷栏怎么调出来_cad左边工具栏不见了怎么办|cad工具栏怎么调出来_PC6教学...
  5. clickhouse
  6. UML用例图怎么画 有手就会
  7. [项目管理]-第十二章:项目监督和控制
  8. 电脑装机必备软件清单
  9. SECS/GEM概念
  10. Windows11 WSL Ubuntu1804 配置指南