|
|
@@ -0,0 +1,88 @@
|
|
|
+package com.zksy.system.basicData.service;
|
|
|
+
|
|
|
+import com.zksy.common.utils.StringUtil;
|
|
|
+import com.zksy.common.utils.uuid.UUID;
|
|
|
+import com.zksy.system.basicData.domain.Captcha;
|
|
|
+import com.zksy.system.utils.CaptchaUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.data.redis.core.StringRedisTemplate;
|
|
|
+import org.springframework.data.redis.core.ValueOperations;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.awt.image.BufferedImage;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class CaptchaService {
|
|
|
+ /**
|
|
|
+ * 拼图验证码允许偏差
|
|
|
+ **/
|
|
|
+ private static Integer ALLOW_DEVIATION = 3;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private StringRedisTemplate stringRedisTemplate;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 校验验证码
|
|
|
+ * @param imageKey
|
|
|
+ * @param imageCode
|
|
|
+ * @return boolean
|
|
|
+ **/
|
|
|
+ public String checkImageCode(String imageKey, String imageCode) {
|
|
|
+ ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
|
|
|
+ String text = ops.get("imageCode:" + imageKey);
|
|
|
+ if(StringUtil.isBlank(text)){
|
|
|
+ return "验证码已失效";
|
|
|
+ }
|
|
|
+ // 根据移动距离判断验证是否成功
|
|
|
+ if (Math.abs(Integer.parseInt(text) - Integer.parseInt(imageCode)) > ALLOW_DEVIATION) {
|
|
|
+ return "验证失败,请控制拼图对齐缺口";
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 缓存验证码,有效期15分钟
|
|
|
+ * @param key
|
|
|
+ * @param code
|
|
|
+ **/
|
|
|
+ public void saveImageCode(String key, String code) {
|
|
|
+ ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
|
|
|
+ ops.set("imageCode:" + key, code, 15, TimeUnit.MINUTES);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取验证码拼图(生成的抠图和带抠图阴影的大图及抠图坐标)
|
|
|
+ **/
|
|
|
+ public Object getCaptcha(Captcha captcha) {
|
|
|
+ //参数校验
|
|
|
+ CaptchaUtils.checkCaptcha(captcha);
|
|
|
+ //获取画布的宽高
|
|
|
+ int canvasWidth = captcha.getCanvasWidth();
|
|
|
+ int canvasHeight = captcha.getCanvasHeight();
|
|
|
+ //获取阻塞块的宽高/半径
|
|
|
+ int blockWidth = captcha.getBlockWidth();
|
|
|
+ int blockHeight = captcha.getBlockHeight();
|
|
|
+ int blockRadius = captcha.getBlockRadius();
|
|
|
+ //获取资源图
|
|
|
+ BufferedImage canvasImage = CaptchaUtils.getBufferedImage(captcha.getPlace());
|
|
|
+ //调整原图到指定大小
|
|
|
+ canvasImage = CaptchaUtils.imageResize(canvasImage, canvasWidth, canvasHeight);
|
|
|
+ //随机生成阻塞块坐标
|
|
|
+ int blockX = CaptchaUtils.getNonceByRange(blockWidth, canvasWidth - blockWidth - 10);
|
|
|
+ int blockY = CaptchaUtils.getNonceByRange(10, canvasHeight - blockHeight + 1);
|
|
|
+ //阻塞块
|
|
|
+ BufferedImage blockImage = new BufferedImage(blockWidth, blockHeight, BufferedImage.TYPE_4BYTE_ABGR);
|
|
|
+ //新建的图像根据轮廓图颜色赋值,源图生成遮罩
|
|
|
+ CaptchaUtils.cutByTemplate(canvasImage, blockImage, blockWidth, blockHeight, blockRadius, blockX, blockY);
|
|
|
+ // 移动横坐标
|
|
|
+ String nonceStr = UUID.randomUUID().toString().replaceAll("-", "");
|
|
|
+ // 缓存
|
|
|
+ saveImageCode(nonceStr,String.valueOf(blockX));
|
|
|
+ //设置返回参数
|
|
|
+ captcha.setNonceStr(nonceStr);
|
|
|
+ captcha.setBlockY(blockY);
|
|
|
+ captcha.setBlockSrc(CaptchaUtils.toBase64(blockImage, "png"));
|
|
|
+ captcha.setCanvasSrc(CaptchaUtils.toBase64(canvasImage, "png"));
|
|
|
+ return captcha;
|
|
|
+ }
|
|
|
+}
|