-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSliderCheckUtil.java
More file actions
238 lines (213 loc) · 8.31 KB
/
SliderCheckUtil.java
File metadata and controls
238 lines (213 loc) · 8.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
package com.cnhis.cloudhealth.crm.common.SliderCheck;
import com.cnhis.cloudhealth.crm.common.log.ToolLogger;
import com.cnhis.cloudhealth.crm.common.log.ToolLoggerFactory;
import org.apache.commons.codec.binary.Base64;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Random;
/**
* 滑块验证码工具类
* Copyright (c) 2019 Choice, Inc.
* All Rights Reserved.
* Choice Proprietary and Confidential.
*
* @author oy
* @since 2019/8/22 19:51
*/
public class SliderCheckUtil {
private static final ToolLogger TOOL_LOGGER = ToolLoggerFactory.getLogger(SliderCheckUtil.class);
/**
* 背景图数量, 随机生成之一
*/
private static int BG_COUNT = 3;
/**
* 图片素材路径
* 滑块形状名称: slider_icon.png
* 滑动阴影名称: slider_icon_bg.png
*/
private static final String FILE_PATH = "static/sliderCheck";
/**
* 背景图片路径
* 默认背景图片名称: slider_bg_%d.jpg
*/
private static final String BG_FILE_PATH = FILE_PATH + "/bg";
/**
* 滑动容错范围, 默认:10, 表示校验X轴时左右10个单位内都算正确
*/
private static final int SLIDER_RANGE = 10;
static {
URL resource = SliderCheckUtil.class.getClassLoader().getResource(BG_FILE_PATH);
if (resource != null) {
File file = new File(resource.getPath());
if (file != null) {
File[] files = file.listFiles();
if (files != null) {
BG_COUNT = files.length;
}
}
}
}
/**
* 生成滑块对象
* @return
*/
public static SliderCheck build() {
if (BG_COUNT == 0) {
TOOL_LOGGER.error("图形滑块验证码异常: 请上传背景图");
return null;
}
try {
Random random = new Random();
int num = random.nextInt(BG_COUNT) + 1;
String bgPath = String.format("%s/slider_bg_%d.jpg", BG_FILE_PATH, num);
String iconPath = String.format("%s/slider_icon.png", FILE_PATH);
String puzzlePath = String.format("%s/slider_icon_bg.png", FILE_PATH);
// 滑块图标
ClassLoader classLoader = SliderCheckUtil.class.getClassLoader();
InputStream iconStream = classLoader.getResourceAsStream(iconPath);
if (iconStream == null) {
TOOL_LOGGER.error("图形滑块验证码异常: 请上传滑块图标");
return null;
}
// 滑块背景图标
InputStream puzzleStream = classLoader.getResourceAsStream(puzzlePath);
if (iconStream == null) {
TOOL_LOGGER.error("图形滑块验证码异常: 请上传滑块背景图标");
return null;
}
// 背景图
InputStream bgStream = classLoader.getResourceAsStream(bgPath);
if (iconStream == null) {
TOOL_LOGGER.error("图形滑块验证码异常: 请上传背景图");
return null;
}
BufferedImage iconImg = ImageIO.read(iconStream);
int[][] blockData = getIconData(iconImg);
int iconWidth = iconImg.getWidth();
int iconHeight = iconImg.getHeight();
BufferedImage puzzleImg = ImageIO.read(puzzleStream);
BufferedImage bgImg = ImageIO.read(bgStream);
// 四边减小滑块宽高作为滑动区域
int bgWidth = bgImg.getWidth();
int maxX = bgWidth - iconWidth * 2;
int x = random.nextInt(maxX) + iconWidth;
int bgHeight = bgImg.getHeight();
int maxY = bgHeight - iconHeight;
int y = random.nextInt(maxY);
cutByTemplate(bgImg, iconImg, puzzleImg, blockData, x, y);
String bgImgSt = getImageBASE64(bgImg, "jpg");
String puzzleImgSt = getImageBASE64(puzzleImg, "png");
SliderCheck sliderCheck = new SliderCheck();
sliderCheck.setResourceImg(bgImgSt);
sliderCheck.setResourceWidth(bgWidth);
sliderCheck.setResourceHeight(bgHeight);
sliderCheck.setPuzzleImg(puzzleImgSt);
sliderCheck.setPuzzleWidth(iconWidth);
sliderCheck.setPuzzleHeight(iconHeight);
sliderCheck.setPuzzleXAxis(x);
sliderCheck.setPuzzleYAxis(y);
return sliderCheck;
} catch (Exception e) {
TOOL_LOGGER.error("创建图形滑块验证码异常:", e);
return null;
}
}
/**
* 校验滑块
* @param sliderCheck 滑块对象
* @param distance 滑动距离
* @return
*/
public static boolean verifySlider(SliderCheck sliderCheck, Integer distance) {
return sliderCheck != null && verifySlider(sliderCheck.getPuzzleXAxis(), distance);
}
/**
* 校验滑块
* @param puzzleXAxis 滑块对象X轴
* @param distance 滑动距离
* @return
*/
public static boolean verifySlider(Integer puzzleXAxis, Integer distance) {
return puzzleXAxis != null
&& distance != null
&& distance > 0
&& distance > puzzleXAxis - SLIDER_RANGE && distance < puzzleXAxis + SLIDER_RANGE;
}
/**
* 转换图片Base64
* @param image
* @param formatName
* @return
* @throws IOException
*/
public static String getImageBASE64(BufferedImage image, String formatName) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(image, formatName, out);
byte[] b = out.toByteArray();
return new String(Base64.encodeBase64(b));//生成base64编码
}
/**
* 根据png图生成图片轮廓
* @param icon
* @return
* @throws Exception
*/
private static int[][] getIconData(BufferedImage icon) throws Exception {
int[][] data = new int[icon.getWidth()][icon.getHeight()];
for (int i = 0; i < icon.getWidth(); i++) {
for (int j = 0; j < icon.getHeight(); j++) {
int rgb = icon.getRGB(i, j);
data[i][j] = rgb == 0 ? 0 : 1;
}
}
return data;
}
/**
*
* @Createdate: 2019年1月24日上午10:51:30
* @Title: cutByTemplate
* @Description: 生成小图片、给大图片添加阴影
* @author mzl
* @param bgImg
* @param puzzleImg
* @param blockData
* @param x
* @param y void
* @throws
*/
private static void cutByTemplate(BufferedImage bgImg, BufferedImage iconImage, BufferedImage puzzleImg, int[][] blockData, int x, int y) {
for (int i = 0; i < blockData.length; i++) {
int[] data = blockData[i];
for (int j = 0; j < data.length; j++) {
int rgb = data[j];
// 原图中对应位置变色处理
int rgb_ori = bgImg.getRGB(x + i, y + j);
if (rgb == 1) {
// 抠图上复制对应颜色值
puzzleImg.setRGB(i, j, rgb_ori);
// 原图对应位置颜色变化(原图通过绘制的方式进行图层叠加)
// bgImg.setRGB(x + i, y + j, rgb_ori & 0x363636);
}else{
// 这里把背景设为透明(背景图自带阴影, 这里不作处理)
// puzzleImg.setRGB(i, j, rgb_ori & 0xffffff);
}
}
}
// 绘制背景图
Graphics2D g2d = bgImg.createGraphics();
int imgWidth = iconImage.getWidth();
int imgHeight = iconImage.getHeight();
// 在图形和图像中实现混合和透明效果
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1f));
// 绘制
g2d.drawImage(iconImage, x, y, imgWidth, imgHeight, null);
// 释放图形上下文使用的系统资源
g2d.dispose();
}
}