CaptchaService.java 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. package com.zksy.system.basicData.service;
  2. import com.zksy.common.utils.StringUtil;
  3. import com.zksy.common.utils.uuid.UUID;
  4. import com.zksy.system.basicData.domain.Captcha;
  5. import com.zksy.system.utils.CaptchaUtils;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.data.redis.core.StringRedisTemplate;
  8. import org.springframework.data.redis.core.ValueOperations;
  9. import org.springframework.stereotype.Service;
  10. import java.awt.image.BufferedImage;
  11. import java.util.concurrent.TimeUnit;
  12. @Service
  13. public class CaptchaService {
  14. /**
  15. * 拼图验证码允许偏差
  16. **/
  17. private static Integer ALLOW_DEVIATION = 5;
  18. @Autowired
  19. private StringRedisTemplate stringRedisTemplate;
  20. /**
  21. * 校验验证码
  22. * @param imageKey
  23. * @param imageCode
  24. * @return boolean
  25. **/
  26. public String checkImageCode(String imageKey, String imageCode) {
  27. ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
  28. String text = ops.get("imageCode:" + imageKey);
  29. if(StringUtil.isBlank(text)){
  30. return "验证码已失效";
  31. }
  32. // 根据移动距离判断验证是否成功
  33. if (Math.abs(Integer.parseInt(text) - Integer.parseInt(imageCode)) > ALLOW_DEVIATION) {
  34. return "验证失败,请控制拼图对齐缺口";
  35. }
  36. return null;
  37. }
  38. /**
  39. * 缓存验证码,有效期15分钟
  40. * @param key
  41. * @param code
  42. **/
  43. public void saveImageCode(String key, String code) {
  44. ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
  45. ops.set("imageCode:" + key, code, 15, TimeUnit.MINUTES);
  46. }
  47. /**
  48. * 获取验证码拼图(生成的抠图和带抠图阴影的大图及抠图坐标)
  49. **/
  50. public Object getCaptcha(Captcha captcha) {
  51. //参数校验
  52. CaptchaUtils.checkCaptcha(captcha);
  53. //获取画布的宽高
  54. int canvasWidth = captcha.getCanvasWidth();
  55. int canvasHeight = captcha.getCanvasHeight();
  56. //获取阻塞块的宽高/半径
  57. int blockWidth = captcha.getBlockWidth();
  58. int blockHeight = captcha.getBlockHeight();
  59. int blockRadius = captcha.getBlockRadius();
  60. //获取资源图
  61. BufferedImage canvasImage = CaptchaUtils.getBufferedImage(captcha.getPlace());
  62. //调整原图到指定大小
  63. canvasImage = CaptchaUtils.imageResize(canvasImage, canvasWidth, canvasHeight);
  64. //随机生成阻塞块坐标
  65. int blockX = CaptchaUtils.getNonceByRange(blockWidth, canvasWidth - blockWidth - 10);
  66. int blockY = CaptchaUtils.getNonceByRange(10, canvasHeight - blockHeight + 1);
  67. //阻塞块
  68. BufferedImage blockImage = new BufferedImage(blockWidth, blockHeight, BufferedImage.TYPE_4BYTE_ABGR);
  69. //新建的图像根据轮廓图颜色赋值,源图生成遮罩
  70. CaptchaUtils.cutByTemplate(canvasImage, blockImage, blockWidth, blockHeight, blockRadius, blockX, blockY);
  71. // 移动横坐标
  72. String nonceStr = UUID.randomUUID().toString().replaceAll("-", "");
  73. // 缓存
  74. saveImageCode(nonceStr,String.valueOf(blockX));
  75. //设置返回参数
  76. captcha.setNonceStr(nonceStr);
  77. captcha.setBlockY(blockY);
  78. captcha.setBlockSrc(CaptchaUtils.toBase64(blockImage, "png"));
  79. captcha.setCanvasSrc(CaptchaUtils.toBase64(canvasImage, "png"));
  80. return captcha;
  81. }
  82. }