diff --git a/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-application/schisandra-cloud-storage-auth-application-controller/src/main/java/com/schisandra/auth/application/config/SmsInitConfig.java b/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-application/schisandra-cloud-storage-auth-application-controller/src/main/java/com/schisandra/auth/application/config/SmsInitConfig.java index 3d157dc..3df73ac 100644 --- a/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-application/schisandra-cloud-storage-auth-application-controller/src/main/java/com/schisandra/auth/application/config/SmsInitConfig.java +++ b/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-application/schisandra-cloud-storage-auth-application-controller/src/main/java/com/schisandra/auth/application/config/SmsInitConfig.java @@ -23,7 +23,6 @@ public class SmsInitConfig { List SchisandraSmsConfigBOs= schisandraSmsConfigDomainService.queryAll(); List schisandraSmsConfigDTOS = SchisandraSmsConfigDTOConvert.INSTANCE.convertBOToDTOList(SchisandraSmsConfigBOs); for (SchisandraSmsConfigDTO schisandraSmsConfig : schisandraSmsConfigDTOS){ - System.out.println(schisandraSmsConfig.toString()); if (schisandraSmsConfig!=null){ // 创建SmsBlend 短信实例 SmsFactory.createSmsBlend(smsReadConfig); diff --git a/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-application/schisandra-cloud-storage-auth-application-controller/src/main/java/com/schisandra/auth/application/controller/ReactRotateCaptchaController.java b/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-application/schisandra-cloud-storage-auth-application-controller/src/main/java/com/schisandra/auth/application/controller/ReactRotateCaptchaController.java index 11a3ca6..e3262bb 100644 --- a/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-application/schisandra-cloud-storage-auth-application-controller/src/main/java/com/schisandra/auth/application/controller/ReactRotateCaptchaController.java +++ b/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-application/schisandra-cloud-storage-auth-application-controller/src/main/java/com/schisandra/auth/application/controller/ReactRotateCaptchaController.java @@ -2,6 +2,12 @@ package com.schisandra.auth.application.controller; import cn.hutool.core.lang.Assert; +import com.schisandra.auth.common.entity.CaptchaResult; +import com.schisandra.auth.common.entity.Result; +import com.schisandra.auth.common.redis.RedisUtil; +import com.schisandra.auth.common.utils.AESUtils; +import com.schisandra.auth.common.utils.RotateImageUtils; +import com.schisandra.auth.common.utils.SmsCodeUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; @@ -11,97 +17,87 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import javax.annotation.Resource; import javax.imageio.ImageIO; +import java.awt.*; import java.awt.image.BufferedImage; import java.io.*; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.Base64; +import java.util.HashMap; +import java.util.Random; +import java.util.concurrent.TimeUnit; @RestController @RequestMapping("/ReactRotateCaptcha/") @Slf4j public class ReactRotateCaptchaController { - @PostMapping (value = "get", produces = MediaType.IMAGE_PNG_VALUE) - public ResponseEntity get(){ - //前端可以直接根据URL:/image/{图片id} 来获取图片 注意:资源文件ID最好进行加密和设置有效期 - // 在实际开发中 一般先通过图片id查看数据库有没有这条记录 - String imageFilePath = "D:\\java_project\\schisandra-cloud-storage\\schisandra-cloud-storage-auth\\schisandra-cloud-storage-auth-application\\schisandra-cloud-storage-auth-application-controller\\src\\main\\java\\com\\schisandra\\auth\\application\\image\\test1.png"; - File file = new File(imageFilePath); - try { - BufferedImage bufferedImage = ImageIO.read(file); - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - ImageIO.write(bufferedImage, "png", byteArrayOutputStream); - byte[] imageBytes = byteArrayOutputStream.toByteArray(); // 读取图片数据的字节数组 - // 将图片字节数组转换为Base64编码的字符串 - String base64Image = Base64.getEncoder().encodeToString(imageBytes); - System.out.println(base64Image); - // 创建包含Base64编码的响应体的ResponseEntity对象,并设置正确的媒体类型和内容长度 - return ResponseEntity.ok().contentType(MediaType.IMAGE_PNG) - .body(base64Image); - }catch (Exception e) { - e.printStackTrace(); - } - return ResponseEntity.ok().body(null); - } + @Resource + private RedisUtil redisUtil; + + public final String authRotateCaptchaPrefix = "auth.RotateCaptcha"; /** - * 请求图片地址, 返回的结果进行base64编码 - * @param imgUrl 图片地址 - * @return + * @description:获取图片 + * @param: [] + * @return: java.lang.String + * @author zlg + * @date: 2024/5/10 16:28 */ -// public static String requestUrlToBase64(String imgUrl) { -// //读取图片字节数组 -// byte[] data = null; -// try { -// InputStream in = new FileInputStream(imgUrl); -//// System.out.println("文件大小(字节)=" + in.available()); -// data = new byte[in.available()]; -// in.read(data); -// in.close(); -// } catch (IOException e) { -// e.printStackTrace(); -// } -// //对字节数组进行Base64编码,得到Base64编码的字符串 -// return new String(Base64.encodeBase64(data)); -// -// } -// -// public static File convertBase64ToFile(String fileBase64String, String filePath, String fileName) { -// BufferedOutputStream bos = null; -// FileOutputStream fos = null; -// File file = null; -// try { -// File dir = new File(filePath); -// //判断文件目录是否存在 -// if (!dir.exists() && dir.isDirectory()) { -// dir.mkdirs(); -// } -// byte[] bfile = Base64.decodeBase64(fileBase64String); -// file = new File(filePath + File.separator + fileName); -// fos = new FileOutputStream(file); -// bos = new BufferedOutputStream(fos); -// bos.write(bfile); -// return file; -// } catch (Exception e) { -// e.printStackTrace(); -// } finally { -// if (bos != null) { -// try { -// bos.close(); -// } catch (IOException e1) { -// e1.printStackTrace(); -// } -// } -// if (fos != null) { -// try { -// fos.close(); -// } catch (IOException e1) { -// e1.printStackTrace(); -// } -// } -// } -// return null; -// } + @PostMapping("get") + public CaptchaResult get() throws Exception { + HashMap map = new HashMap<>(); + RotateImageUtils rotateImageUtils = new RotateImageUtils(); + + InputStream inputStream= ReactRotateCaptchaController.class.getClassLoader().getResourceAsStream("image/test1.jpg"); + BufferedImage image = ImageIO.read(inputStream); + Random random = new Random(); + double randomNumber = random.nextInt(280) + 40; + String key = AESUtils.getKey(); + String token = AESUtils.encrypt(String.valueOf(randomNumber), key); + String prefix = redisUtil.buildKey(authRotateCaptchaPrefix, token); + redisUtil.setNx(prefix, String.valueOf(randomNumber), 60L, TimeUnit.SECONDS); + try { + BufferedImage image1 = rotateImageUtils.rotateImage(image, randomNumber, Color.black); + map.put("token",token); + map.put("str", RotateImageUtils.BufferedImageToBase64(image1)); + return CaptchaResult.ok(map); + } catch (Exception e) { + return CaptchaResult.fail(); + } + } + + + /** + * @description: 验证图片 + * @param: [token, num] + * @return: com.schisandra.auth.common.entity.Result + * @author zlg + * @date: 2024/5/10 17:25 + */ + @PostMapping("verfiy") + public CaptchaResult verfiy(String token, Double num) { + if (num == null && token == null) { + return CaptchaResult.fail(); + } + String prefix = redisUtil.buildKey(authRotateCaptchaPrefix, token); + if (redisUtil.exist(prefix)) { + double realNum = Double.parseDouble(redisUtil.get(prefix)); + if (Math.abs(realNum - num) / realNum < 0.05) { + redisUtil.del(prefix); + return CaptchaResult.ok(); + } else { + return CaptchaResult.fail(); + } + } else { + return CaptchaResult.fail(); + } + + + } + } diff --git a/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-application/schisandra-cloud-storage-auth-application-controller/src/main/java/com/schisandra/auth/application/controller/SchisandraOauthController.java b/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-application/schisandra-cloud-storage-auth-application-controller/src/main/java/com/schisandra/auth/application/controller/SchisandraOauthController.java index df9a4cc..c3b5d8a 100644 --- a/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-application/schisandra-cloud-storage-auth-application-controller/src/main/java/com/schisandra/auth/application/controller/SchisandraOauthController.java +++ b/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-application/schisandra-cloud-storage-auth-application-controller/src/main/java/com/schisandra/auth/application/controller/SchisandraOauthController.java @@ -5,6 +5,7 @@ import cn.hutool.json.JSONUtil; import com.xkcoding.justauth.AuthRequestFactory; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; + import me.zhyd.oauth.config.AuthSource; import me.zhyd.oauth.model.AuthCallback; import me.zhyd.oauth.model.AuthResponse; diff --git a/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-application/schisandra-cloud-storage-auth-application-controller/src/main/resources/image/test1.jpg b/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-application/schisandra-cloud-storage-auth-application-controller/src/main/resources/image/test1.jpg new file mode 100644 index 0000000..a4498f7 Binary files /dev/null and b/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-application/schisandra-cloud-storage-auth-application-controller/src/main/resources/image/test1.jpg differ diff --git a/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-common/pom.xml b/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-common/pom.xml index 500e848..c8a657a 100644 --- a/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-common/pom.xml +++ b/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-common/pom.xml @@ -92,9 +92,10 @@ org.dromara.sms4j sms4j-spring-boot-starter - 3.2.1 + 3.2.1 + org.dromara.sms4j sms4j-Email-core @@ -108,12 +109,6 @@ 1.1.0 - - - org.projectlombok - lombok - true - @@ -122,12 +117,6 @@ 5.3.8 - - - com.google.guava - guava - 29.0-jre - org.apache.directory.studio diff --git a/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-common/src/main/java/com/schisandra/auth/common/entity/CaptchaResult.java b/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-common/src/main/java/com/schisandra/auth/common/entity/CaptchaResult.java new file mode 100644 index 0000000..4eb6bb4 --- /dev/null +++ b/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-common/src/main/java/com/schisandra/auth/common/entity/CaptchaResult.java @@ -0,0 +1,46 @@ +package com.schisandra.auth.common.entity; + +import lombok.Data; + +@Data +public class CaptchaResult { + + private Integer code; + + private String msg; + + private T data; + + public static CaptchaResult ok() { + CaptchaResult result = new CaptchaResult(); + + result.setCode(0); + result.setMsg("Success"); + return result; + } + + public static CaptchaResult ok(T data) { + CaptchaResult result = new CaptchaResult(); + + result.setCode(0); + result.setMsg("Success"); + result.setData(data); + return result; + } + + public static CaptchaResult fail() { + CaptchaResult result = new CaptchaResult(); + + result.setCode(1); + result.setMsg("Fail"); + return result; + } + + public static CaptchaResult fail(T data) { + CaptchaResult result = new CaptchaResult(); + result.setCode(1); + result.setMsg("Fail"); + result.setData(data); + return result; + } +} diff --git a/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-common/src/main/java/com/schisandra/auth/common/utils/RotateImageUtils.java b/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-common/src/main/java/com/schisandra/auth/common/utils/RotateImageUtils.java new file mode 100644 index 0000000..2a3b6dd --- /dev/null +++ b/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-common/src/main/java/com/schisandra/auth/common/utils/RotateImageUtils.java @@ -0,0 +1,177 @@ +package com.schisandra.auth.common.utils; + +import sun.misc.BASE64Decoder; +import sun.misc.BASE64Encoder; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Map; + +public class RotateImageUtils { + + public static Color bgColor = new Color(255, 255, 255); + + + /** + * @description: 压缩图片并将图片转换成base64 + * @param: [bufferedImage] + * @return: java.lang.String + * @author zlg + * @date: 2024/5/9 13:13 + */ + public static String BufferedImageToBase64(BufferedImage bufferedImage) throws IOException { + int targetWidth = 400; + int targetHeight = 400; + // 获取原始图片的尺寸 + int originalWidth = bufferedImage.getWidth(); + int originalHeight = bufferedImage.getHeight(); + // 创建一个新的 BufferedImage,用于存放处理后的图片 + BufferedImage outputImage = new BufferedImage(targetWidth, targetHeight, bufferedImage.getType()); + // 创建一个 Graphics2D 对象,用于绘制新图片 + Graphics2D graphics = outputImage.createGraphics(); + // 如果原始图片尺寸大于目标尺寸,则进行压缩 + if (originalWidth > targetWidth || originalHeight > targetHeight) { + Image scaledImage = bufferedImage.getScaledInstance(targetWidth, targetHeight, Image.SCALE_SMOOTH); + graphics.drawImage(scaledImage, 0, 0, null); + } + graphics.dispose(); + ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流 + ImageIO.write(outputImage, "png", baos);//写入流中 + byte[] bytes = baos.toByteArray();//转换成字节 + BASE64Encoder encoder = new BASE64Encoder(); + String png_base64 = encoder.encodeBuffer(bytes).trim();//转换成base64串 + png_base64 = png_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n + return "data:image/jpg;base64," + png_base64; + + } + + /** + * @description: 将base64转换成图片 + * @param: [base64] + * @return: java.awt.image.BufferedImage + * @author zlg + * @date: 2024/5/9 13:14 + */ + public static BufferedImage base64ToBufferedImage(String base64) { + BASE64Decoder decoder = new sun.misc.BASE64Decoder(); + try { + byte[] bytes1 = decoder.decodeBuffer(base64); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes1); + return ImageIO.read(bais); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + /** + * @description: 获取旋转后的图片 + * @param: [image, theta, backgroundColor] + * @return: java.awt.image.BufferedImage + * @author zlg + * @date: 2024/5/9 13:14 + */ + public BufferedImage rotateImage(BufferedImage image, double theta, Color backgroundColor) { + int width = image.getWidth(); + int height = image.getHeight(); + double angle = theta * Math.PI / 180; // 度转弧度 + double[] xCoords = getX(width / 2, height / 2, angle); + double[] yCoords = getY(width / 2, height / 2, angle); + int WIDTH = (int) (xCoords[3] - xCoords[0]); + int HEIGHT = (int) (yCoords[3] - yCoords[0]); + BufferedImage resultImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); + for (int i = 0; i < WIDTH; i++) { + for (int j = 0; j < HEIGHT; j++) { + int x = i - WIDTH / 2; + int y = HEIGHT / 2 - j; + double radius = Math.sqrt(x * x + y * y); + double angle1; + if (y > 0) { + angle1 = Math.acos(x / radius); + } else { + angle1 = 2 * Math.PI - Math.acos(x / radius); + } + x = (int) Math.round(radius * Math.cos(angle1 - angle)); + y = (int) Math.round(radius * Math.sin(angle1 - angle)); + if (x < (width / 2) & x > -(width / 2) & y < (height / 2) & y > -(height / 2)) { + int rgb = image.getRGB((int) Math.round(x + width / 2), (int) Math.round(height / 2 - y)); + resultImage.setRGB(i, j, rgb); + } else { + resultImage.setRGB(i, j, -1); + } + } + } + return resultImage; + } + + // 获取四个角点旋转后Y方向坐标 + private double[] getY(int i, int j, double angle) { + double results[] = new double[4]; + double radius = Math.sqrt(i * i + j * j); + double angle1 = Math.asin(j / radius); + results[0] = radius * Math.sin(angle1 + angle); + results[1] = radius * Math.sin(Math.PI - angle1 + angle); + results[2] = -results[0]; + results[3] = -results[1]; + Arrays.sort(results); + return results; + } + + // 获取四个角点旋转后X方向坐标 + private double[] getX(int i, int j, double angle) { + double results[] = new double[4]; + double radius = Math.sqrt(i * i + j * j); + double angle1 = Math.acos(i / radius); + results[0] = radius * Math.cos(angle1 + angle); + results[1] = radius * Math.cos(Math.PI - angle1 + angle); + results[2] = -results[0]; + results[3] = -results[1]; + Arrays.sort(results); + return results; + } + + /** + * @description: 获取旋转后的图片 + * @param: [image] + * @return: java.awt.image.BufferedImage + * @author zlg + * @date: 2024/5/9 13:14 + */ + public BufferedImage writeCyclePic(BufferedImage image) { + BufferedImage newImage = new BufferedImage(350, 350, BufferedImage.TYPE_INT_BGR); + try { + int width = image.getWidth(); + int heigth = image.getHeight(); + double x0 = width / 2; + double y0 = heigth / 2; + int woffset = (width - 350) / 2; + int hoffset = (heigth - 350) / 2; + for (int i = woffset; i < 350 + woffset; i++) { + for (int j = hoffset; j < 350 + hoffset; j++) { + double r = Math.sqrt(Math.pow(Math.abs(i - x0), 2.0) + Math.pow(Math.abs(j - y0), 2.0)); + if (r > (x0 - woffset)) { + newImage.setRGB(i - woffset, j - hoffset, -1); + } else { + newImage.setRGB(i - woffset, j - hoffset, image.getRGB(i, j)); + } + } + } + return newImage; + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + } + + + + +} diff --git a/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-starter/pom.xml b/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-starter/pom.xml index 746aa35..f58e2ae 100644 --- a/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-starter/pom.xml +++ b/schisandra-cloud-storage-auth/schisandra-cloud-storage-auth-starter/pom.xml @@ -37,7 +37,6 @@ spring-cloud-starter-bootstrap - com.schisandra schisandra-cloud-storage-auth-application-controller