java图片滑动验证(登录验证)原理与实现方法详解
作者:我走小路 发布时间:2023-07-10 13:29:53
标签:java,图片,滑动验证,登录验证
本文实例讲述了java图片滑动验证(登录验证)原理与实现方法。分享给大家供大家参考,具体如下:
这是我简单做出的效果图,处理300X150px的校验图,并把图片发到前端,用时50毫秒左右,速度还是非常快的。
原理:
1.利用java从大图中随机抠出一张小图,并在大图上给抠出小图的位置加阴影,然后把这两张图片返回给前端;
2.前端获取图片,用户滑动小图到阴影的位置,获取小图滑动的距离,返回给java后台进行校验;
3.校验通过,返回校验通过编号;
4.前端调登录接口,把账号、密码、和校验编号传到Java后台进行登录。
实现:
1.计算需要的小图轮廓,用二维数组来表示,二维数组有两张值,0和1,其中0表示没有颜色,1有颜色,如下图,我要抠图的轮廓是这样的:
左边和下边有有半圆,这个根据圆的公式就可以了,代码示例:
static int targetLength=55;//小图长
static int targetWidth=45;//小图宽
static int circleR=6;//半径
static int r1=3;//距离点
/**
*
* @Createdate: 2019年1月24日上午10:52:42
* @Title: getBlockData
* @Description: 生成小图轮廓
* @author mzl
* @return int[][]
* @throws
*/
private static int[][] getBlockData() {
int[][] data = new int[targetLength][targetWidth];
double x2 = targetLength-circleR;
//随机生成圆的位置
double h1 = circleR + Math.random() * (targetWidth-3*circleR-r1);
double po = circleR*circleR;
double xbegin = targetLength-circleR-r1;
double ybegin = targetWidth-circleR-r1;
for (int i = 0; i < targetLength; i++) {
for (int j = 0; j < targetWidth; j++) {
double d3 = Math.pow(i - x2,2) + Math.pow(j - h1,2);
double d2 = Math.pow(j-2,2) + Math.pow(i - h1,2);
if ((j <= ybegin && d2 <= po)||(i >= xbegin && d3 >= po)) {
data[i][j] = 0;
} else {
data[i][j] = 1;
}
}
}
return data;
}
2.根据计算处理的小图轮廓,在大图上抠图
/**
*
* @Createdate: 2019年1月24日上午10:51:30
* @Title: cutByTemplate
* @Description: 生成小图片、给大图片添加阴影
* @author mzl
* @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){
for (int i = 0; i < targetLength; i++) {
for (int j = 0; j < targetWidth; j++) {
int rgb = templateImage[i][j];
// 原图中对应位置变色处理
int rgb_ori = oriImage.getRGB(x + i, y + j);
if (rgb == 1) {
//抠图上复制对应颜色值
targetImage.setRGB(i, j, rgb_ori);
//原图对应位置颜色变化
oriImage.setRGB(x + i, y + j, rgb_ori & 0x363636 );
}else{
//这里把背景设为透明
targetImage.setRGB(i, j, rgb_ori & 0x00ffffff);
}
}
}
}
3.把大图小图转base64码,方便返回给前端
/**
*
* @Createdate: 2019年1月24日上午11:49:42
* @Title: createImage
* @Description: 获取大图,小图Base64码
* @author mzl
* @param url
* @return Map<String,String>
* @throws
*/
public static Map<String,String> createImage(String url,int L,int W,Map<String,String> resultMap){
try {
BufferedImage bufferedImage = ImageIO.read(new FileInputStream(url));
BufferedImage target= new BufferedImage(targetLength, targetWidth, BufferedImage.TYPE_4BYTE_ABGR);
cutByTemplate(bufferedImage,target,getBlockData(),L,W);
resultMap.put("b", getImageBASE64(bufferedImage));//大图
resultMap.put("s", getImageBASE64(target));//小图
} catch (IOException e) {
e.printStackTrace();
}finally{
return resultMap;
}
}
/**
*
* @Createdate: 2019年1月24日上午11:14:19
* @Title: getImageStr
* @Description: 图片转BASE64
* @author mzl
* @param image
* @return
* @throws IOException String
* @throws
*/
public static String getImageBASE64(BufferedImage image) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(image,"png",out);
byte[] b = out.toByteArray();//转成byte数组
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(b);//生成base64编码
}
到此图片验证关键代码完毕。
希望本文所述对大家java程序设计有所帮助。
来源:https://blog.csdn.net/qq_36892341/article/details/86644580


猜你喜欢
- MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。MongoD
- LinkedBlockingDeque介绍LinkedBlockingDeque是双向链表实现的双向并发阻塞队列。该阻塞队列同时支持FIFO
- 如题,有时候看见一个布局写上几百行看上去会非常吃力麻烦,这时候抽取控件样式很有必要了, Android Studio提供了抽取Style样式
- 现如今,验证码在Android的客户端还是非常普遍的.通过手机账号和验证码直接去注册应用账户的信息.很多应用都以这种方式来完成注
- 本文实例讲述了Android使用selector修改TextView中字体颜色和背景色的方法。分享给大家供大家参考,具体如下:android
- 整合Spring Data JPAJPA (Java Persistence API)和 Spring Data 是两个范畴的概念。Hibe
- 前言在分布式场景下为了保证数据最终一致性。在单进程的系统中,存在多个线程可以同时改变某个变量(可变共享变量)时,就需要对变量或代码块做同步(
- 一、什么是命令模式命令模式是一个高内聚的模式,其定义为:将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请 求排队或者记录
- 本文实例为大家分享了C#类的多态性,供大家参考,具体内容如下第一种:编译时的多态性,直接这样说不知道说啥?程序执行过程主要分为三步:编译,链
- 讲解之前需要说明的是旋转屏幕:在系统的自动旋转屏幕开启的情况下,我们旋转屏幕手动设置屏幕:我们自己去调用Activity的 setReque
- Java中IO的模型分为三种,同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。BIO【同步阻塞】在JDK1.4出来之前,我们建立网
- java addMouseListener()方法使用用于接收组件上“感兴趣”的鼠标事件(按下、释放、单击、进入或离开)的 * 接口。(要跟
- 如果不知道,类的静态变量存储在那? 方法的局部变量存储在那? 赶快收藏Java内存区域主要可以分为共享内存,堆、方法区和线程私有内存,虚拟机
- 注解说明使用注解: @PostConstruct效果:在Bean初始化之后(构造方法和@Autowired之后)执行指定操作。经常用在将构造
- 什么是数组数组是相同类型数据的有序集合数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。其中,每一个数据称作一个数组元素,每
- 在Spring中进行事务管理非常简单,只需要在方法上加上注解@Transactional,Spring就可以自动帮我们进行事务的开启、提交、
- 一、题目描述给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种
- 本文实例讲述了Android开发中4个常用的工具类。分享给大家供大家参考,具体如下:1、土司工具类(Toast管理)/** * Toast统
- 简介本文用示例介绍使用MyBatis-Plus进行多表查询的方法,包括静态查询和动态查询。代码controllerpackage com.e
- 注:图片来源于网络SpringBoot作为业内公认的优秀开源框架,它的 * 是如何实现呢?在这里首先对一些基础组件进行分析;1、事件Appl