准备工作
1、若干原图片(下文称为原图)
2、一张抠图形状图片(下文称为滑块模板,抠出来的图称为滑块)
3、一张抠图边框图片(下文称为滑块边框)
注意:滑块模板尺寸必须小于原图尺寸
实现思路
1、后端 - 在若干原图中随机一张原图
2、后端 - 根据滑块模板随机在原图中随机一个矩形区域,并且得到区域x、y坐标,注意随机区域不要超过原图边界
3、后端 - 根据滑块模板在原图上抠图(原理:滑块模板中滑块是有颜色的,根据滑块模板坐标可以直接取到原图坐标,然后在取原图坐标点颜色并赋值到滑块)
4、后端 - 根据滑块模板在原图上设置遮罩缺块(原理:同上取到原图坐标并取得原图色值,把色值调低并放回去就形成遮罩缺块)
5、后端 - 为了用户体验给滑块加边框(原理:滑块边框与滑块模板同等画布,且边框刚好大于滑块,直接取边框中有颜色的坐标,并把颜色设置在滑块上)
6、后端 - 把滑块图片Base64,有缺块的原图Base64
7、后端 - 经过前6步已经可以得到,两个Base64的字符串和一个坐标x、y,随机一个key,把坐标x、y存在redis中
8、后端 - 返回前端两个Base64的字符串和y坐标 和key
9、前端 - 每隔100毫秒获取一次滑块坐标,滑动结束后把key和路径坐标数组返回给后端
10、后端 - 得到key和路径数组后,从redis中取出缺块坐标,用数组中最后一个坐标与缺块坐标比较,差值是否在预设差值范围内,如果不在直接验证失败
11、(可不选)后端 - 为防止机器学习模拟滑块滑动,可以做路径校验,校验原理开始慢,中间快,最后慢(需要慢慢调法值,这里省略)
滑块模板 ![]()
滑块边框![]()
背景图
代码:
public class ImageSlideVerification {
/**
* 源图目录路径
*/
private static String ORIGIN_CATALOG = "original";
/**
* 模板图目录路径
*/
private static String TEMPLATE_CATALOG = "templates";
/**
* 描边图目录路径
*/
private static String BORDER_CATALOG = "templates";
/**
* Image-key
*/
private static String IMAGE_KEY = "IMAGE:KEY:";
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* 获取滑动验证码
* @return
*/
public SlideVerificationVO getSlideCode() {
// 原图
File originalFile = getOriginalFile();
// 滑块模板图
File templateFile = getTemplateFile();
// 滑块描边图片
File borderFile = getBorderFile();
// 生成随机x、y
int x = generateX(originalFile, templateFile);
int y = generateY(originalFile, templateFile);
// 生成滑块
String slide = cutSlideImage(originalFile, templateFile, borderFile, x, y);
// 生成缺块图
String back = cutBackImage(originalFile, templateFile, borderFile, x, y);
// 生成可以
String imageToken = UUID.randomUUID().toString().replace("-", "");
// 放入redis
Map<String, Integer> cacheMap = new HashMap<>();
cacheMap.put("x", x);
cacheMap.put("y", y);
redisTemplate.opsForValue().set(IMAGE_KEY + imageToken, JSONObject.toJSONString(cacheMap), 5, TimeUnit.MINUTES);
SlideVerificationVO vo = new SlideVerificationVO();
vo.setImageToken(imageToken);
vo.setBackImage(back);
vo.setSlideImage(slide);
vo.setY(y + "");
return vo;
}
/**
* 验证滑动验证码
* @param imageToken
* @param imageCode 数据结构 [{x:0,y:0},{x:10,y:10},{x:20,y:20}]
* @return
*/
private boolean checkSlideCode(String imageToken, String imageCode) {
// redis 取值
String json = redisTemplate.opsForValue().get(IMAGE_KEY + imageToken);
if (StringUtils.isEmpty(json)) {
ret

最低0.47元/天 解锁文章
1808

被折叠的 条评论
为什么被折叠?



