diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 1064b9e..1393cd1 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -7,14 +7,14 @@
-
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
index e24ea69..a34fedc 100644
--- a/.idea/encodings.xml
+++ b/.idea/encodings.xml
@@ -1,8 +1,8 @@
-
-
+
+
diff --git a/YuNan-demo/src/main/java/com/yunan/config/GlobalCorsConfig.java b/YuNan-demo/src/main/java/com/yunan/config/GlobalCorsConfig.java
deleted file mode 100644
index 0f44495..0000000
--- a/YuNan-demo/src/main/java/com/yunan/config/GlobalCorsConfig.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.yunan.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.cors.CorsConfiguration;
-import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
-import org.springframework.web.filter.CorsFilter;
-
-@Configuration
-public class GlobalCorsConfig {
- /**
- * 解决跨域问题
- * @return {@link CorsFilter }
- */
- @Bean
- public CorsFilter corsFilter() {
- CorsConfiguration config = new CorsConfiguration();
- // 设置你要允许的网站域名
- config.addAllowedOrigin("http://localhost:3100");
- //允许跨域发送cookie
- config.setAllowCredentials(true);
- //放行全部原始头信息
- config.addAllowedHeader("*");
- //允许所有请求方法跨域调用
- config.addAllowedMethod("*");
- UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
- source.registerCorsConfiguration("/**", config);
- return new CorsFilter(source);
- }
-}
diff --git a/YuNan-demo/.gitignore b/YuNan-system-start/.gitignore
similarity index 100%
rename from YuNan-demo/.gitignore
rename to YuNan-system-start/.gitignore
diff --git a/YuNan-demo/.mvn/wrapper/maven-wrapper.properties b/YuNan-system-start/.mvn/wrapper/maven-wrapper.properties
similarity index 100%
rename from YuNan-demo/.mvn/wrapper/maven-wrapper.properties
rename to YuNan-system-start/.mvn/wrapper/maven-wrapper.properties
diff --git a/YuNan-demo/mvnw b/YuNan-system-start/mvnw
similarity index 100%
rename from YuNan-demo/mvnw
rename to YuNan-system-start/mvnw
diff --git a/YuNan-demo/mvnw.cmd b/YuNan-system-start/mvnw.cmd
similarity index 100%
rename from YuNan-demo/mvnw.cmd
rename to YuNan-system-start/mvnw.cmd
diff --git a/YuNan-demo/pom.xml b/YuNan-system-start/pom.xml
similarity index 94%
rename from YuNan-demo/pom.xml
rename to YuNan-system-start/pom.xml
index 659445e..2b599c9 100644
--- a/YuNan-demo/pom.xml
+++ b/YuNan-system-start/pom.xml
@@ -9,7 +9,7 @@
1.0.0
- YuNan-demo
+ YuNan-system-start
jar
diff --git a/YuNan-demo/src/main/java/com/yunan/YuNanDemoApplication.java b/YuNan-system-start/src/main/java/com/yunan/YuNanDemoApplication.java
similarity index 100%
rename from YuNan-demo/src/main/java/com/yunan/YuNanDemoApplication.java
rename to YuNan-system-start/src/main/java/com/yunan/YuNanDemoApplication.java
diff --git a/YuNan-demo/src/main/java/com/yunan/config/RedisConfig.java b/YuNan-system-start/src/main/java/com/yunan/config/RedisConfig.java
similarity index 91%
rename from YuNan-demo/src/main/java/com/yunan/config/RedisConfig.java
rename to YuNan-system-start/src/main/java/com/yunan/config/RedisConfig.java
index fe12611..5cc3c82 100644
--- a/YuNan-demo/src/main/java/com/yunan/config/RedisConfig.java
+++ b/YuNan-system-start/src/main/java/com/yunan/config/RedisConfig.java
@@ -1,5 +1,6 @@
package com.yunan.config;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
@@ -7,7 +8,9 @@ import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
+
/*告诉spring,运行的时候加载读取这个类*/
+@Slf4j
@Configuration
public class RedisConfig {
@@ -20,6 +23,7 @@ public class RedisConfig {
redisTemplate.setValueSerializer
(new JdkSerializationRedisSerializer());
redisTemplate.setConnectionFactory(connectionFactory);
+ log.info("redis配置已加载!!!");
return redisTemplate;
}
}
diff --git a/YuNan-demo/src/main/java/com/yunan/config/SwaggerConfig.java b/YuNan-system-start/src/main/java/com/yunan/config/SwaggerConfig.java
similarity index 100%
rename from YuNan-demo/src/main/java/com/yunan/config/SwaggerConfig.java
rename to YuNan-system-start/src/main/java/com/yunan/config/SwaggerConfig.java
diff --git a/YuNan-demo/src/main/java/com/yunan/constant/ResponseCode.java b/YuNan-system-start/src/main/java/com/yunan/constant/ResponseCode.java
similarity index 100%
rename from YuNan-demo/src/main/java/com/yunan/constant/ResponseCode.java
rename to YuNan-system-start/src/main/java/com/yunan/constant/ResponseCode.java
diff --git a/YuNan-demo/src/main/java/com/yunan/controller/AuthController.java b/YuNan-system-start/src/main/java/com/yunan/controller/AuthController.java
similarity index 100%
rename from YuNan-demo/src/main/java/com/yunan/controller/AuthController.java
rename to YuNan-system-start/src/main/java/com/yunan/controller/AuthController.java
diff --git a/YuNan-system-start/src/main/java/com/yunan/controller/CaptchaController.java b/YuNan-system-start/src/main/java/com/yunan/controller/CaptchaController.java
new file mode 100644
index 0000000..aa340ee
--- /dev/null
+++ b/YuNan-system-start/src/main/java/com/yunan/controller/CaptchaController.java
@@ -0,0 +1,33 @@
+package com.yunan.controller;
+
+import com.yunan.dto.Captcha;
+import com.yunan.response.R;
+import com.yunan.service.CaptchaService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+
+
+@RestController
+@RequestMapping("/captcha")
+@Api(tags = "验证码拼图")
+public class CaptchaController {
+
+ @Autowired
+ private CaptchaService captchaService;
+
+ @ApiOperation(value = "生成验证码拼图")
+ @PostMapping("get-captcha")
+ public R getCaptcha(@RequestBody Captcha captcha) {
+ return R.ok(captchaService.getCaptcha(captcha));
+ }
+
+}
+
+
diff --git a/YuNan-system-start/src/main/java/com/yunan/dto/Captcha.java b/YuNan-system-start/src/main/java/com/yunan/dto/Captcha.java
new file mode 100644
index 0000000..fcc617f
--- /dev/null
+++ b/YuNan-system-start/src/main/java/com/yunan/dto/Captcha.java
@@ -0,0 +1,56 @@
+package com.yunan.dto;
+
+import lombok.Data;
+
+@Data
+public class Captcha {
+
+ /**
+ * 随机字符串
+ **/
+ private String nonceStr;
+ /**
+ * 验证值
+ **/
+ private String value;
+ /**
+ * 生成的画布的base64
+ **/
+ private String canvasSrc;
+ /**
+ * 画布宽度
+ **/
+ private Integer canvasWidth;
+ /**
+ * 画布高度
+ **/
+ private Integer canvasHeight;
+ /**
+ * 生成的阻塞块的base64
+ **/
+ private String blockSrc;
+ /**
+ * 阻塞块宽度
+ **/
+ private Integer blockWidth;
+ /**
+ * 阻塞块高度
+ **/
+ private Integer blockHeight;
+ /**
+ * 阻塞块凸凹半径
+ **/
+ private Integer blockRadius;
+ /**
+ * 阻塞块的横轴坐标
+ **/
+ private Integer blockX;
+ /**
+ * 阻塞块的纵轴坐标
+ **/
+ private Integer blockY;
+ /**
+ * 图片获取位置
+ **/
+ private Integer place;
+}
diff --git a/YuNan-demo/src/main/java/com/yunan/dto/LoginDTO.java b/YuNan-system-start/src/main/java/com/yunan/dto/LoginDTO.java
similarity index 97%
rename from YuNan-demo/src/main/java/com/yunan/dto/LoginDTO.java
rename to YuNan-system-start/src/main/java/com/yunan/dto/LoginDTO.java
index 3ad94e1..66be2f6 100644
--- a/YuNan-demo/src/main/java/com/yunan/dto/LoginDTO.java
+++ b/YuNan-system-start/src/main/java/com/yunan/dto/LoginDTO.java
@@ -2,11 +2,13 @@ package com.yunan.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
@ApiModel("用户登入请求")
+@Data
public class LoginDTO {
@NotBlank(message = "用户名不能为空")
diff --git a/YuNan-demo/src/main/java/com/yunan/dto/RegisterDTO.java b/YuNan-system-start/src/main/java/com/yunan/dto/RegisterDTO.java
similarity index 91%
rename from YuNan-demo/src/main/java/com/yunan/dto/RegisterDTO.java
rename to YuNan-system-start/src/main/java/com/yunan/dto/RegisterDTO.java
index b0a83f6..189ce2f 100644
--- a/YuNan-demo/src/main/java/com/yunan/dto/RegisterDTO.java
+++ b/YuNan-system-start/src/main/java/com/yunan/dto/RegisterDTO.java
@@ -2,14 +2,16 @@ package com.yunan.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
@ApiModel("用户注册请求")
+@Data
public class RegisterDTO {
@NotBlank(message = "用户名不能为空")
- @ApiModelProperty(value = "用户名", required = true)
+ @ApiModelProperty(value = "用户名")
private String username;
@Email(message = "请输入有效的邮箱")
@@ -20,7 +22,7 @@ public class RegisterDTO {
@ApiModelProperty(value = "密码", required = true)
private String password;
- @ApiModelProperty(value = "验证码")
+ @ApiModelProperty(value = "验证码", required = true)
private String code;
private String token;
diff --git a/YuNan-demo/src/main/java/com/yunan/pojo/User.java b/YuNan-system-start/src/main/java/com/yunan/dto/User.java
similarity index 95%
rename from YuNan-demo/src/main/java/com/yunan/pojo/User.java
rename to YuNan-system-start/src/main/java/com/yunan/dto/User.java
index c834d95..9e96c04 100644
--- a/YuNan-demo/src/main/java/com/yunan/pojo/User.java
+++ b/YuNan-system-start/src/main/java/com/yunan/dto/User.java
@@ -1,4 +1,4 @@
-package com.yunan.pojo;
+package com.yunan.dto;
import java.io.Serializable;
@@ -6,7 +6,7 @@ import java.io.Serializable;
* 用户实体类
*/
public class User implements Serializable {
- private int id;
+ private Integer id;
/** 用户名*/
private String username;
/** 密码*/
@@ -32,7 +32,7 @@ public class User implements Serializable {
'}';
}
- public int getId() {
+ public Integer getId() {
return id;
}
diff --git a/YuNan-demo/src/main/java/com/yunan/handler/GlobalExceptionHandler.java b/YuNan-system-start/src/main/java/com/yunan/handler/GlobalExceptionHandler.java
similarity index 100%
rename from YuNan-demo/src/main/java/com/yunan/handler/GlobalExceptionHandler.java
rename to YuNan-system-start/src/main/java/com/yunan/handler/GlobalExceptionHandler.java
diff --git a/YuNan-demo/src/main/java/com/yunan/mapper/AuthMapper.java b/YuNan-system-start/src/main/java/com/yunan/mapper/AuthMapper.java
similarity index 75%
rename from YuNan-demo/src/main/java/com/yunan/mapper/AuthMapper.java
rename to YuNan-system-start/src/main/java/com/yunan/mapper/AuthMapper.java
index a3f9cfc..eecf0b7 100644
--- a/YuNan-demo/src/main/java/com/yunan/mapper/AuthMapper.java
+++ b/YuNan-system-start/src/main/java/com/yunan/mapper/AuthMapper.java
@@ -1,8 +1,7 @@
package com.yunan.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.yunan.dto.RegisterDTO;
-import com.yunan.pojo.User;
+import com.yunan.dto.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
diff --git a/YuNan-demo/src/main/java/com/yunan/response/ApiResponse.java b/YuNan-system-start/src/main/java/com/yunan/response/ApiResponse.java
similarity index 100%
rename from YuNan-demo/src/main/java/com/yunan/response/ApiResponse.java
rename to YuNan-system-start/src/main/java/com/yunan/response/ApiResponse.java
diff --git a/YuNan-demo/src/main/java/com/yunan/response/ErrorResponse.java b/YuNan-system-start/src/main/java/com/yunan/response/ErrorResponse.java
similarity index 100%
rename from YuNan-demo/src/main/java/com/yunan/response/ErrorResponse.java
rename to YuNan-system-start/src/main/java/com/yunan/response/ErrorResponse.java
diff --git a/YuNan-system-start/src/main/java/com/yunan/response/R.java b/YuNan-system-start/src/main/java/com/yunan/response/R.java
new file mode 100644
index 0000000..765b6b5
--- /dev/null
+++ b/YuNan-system-start/src/main/java/com/yunan/response/R.java
@@ -0,0 +1,70 @@
+package com.yunan.response;
+
+public class R {
+
+ private int code; // 状态码,200代表成功,其他代表失败
+ private String message; // 响应信息
+ private Object data; // 响应数据
+
+ // 默认构造函数
+ public R() {
+ }
+
+ // 构造函数
+ public R(int code, String message, Object data) {
+ this.code = code;
+ this.message = message;
+ this.data = data;
+ }
+
+ // 成功返回
+ public static R ok(Object data) {
+ return new R(200, "成功", data); // 200代表成功
+ }
+
+ // 错误返回
+ public static R error(String message) {
+ return new R(500, message, null); // 500代表服务器错误,message为错误信息
+ }
+
+ // 错误返回,带code和message
+ public static R error(int code, String message) {
+ return new R(code, message, null); // 根据传入的code返回不同的错误
+ }
+
+ // get 和 set 方法
+ public int getCode() {
+ return code;
+ }
+
+ public void setCode(int code) {
+ this.code = code;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ // 重写toString方法,方便调试输出
+ @Override
+ public String toString() {
+ return "R{" +
+ "code=" + code +
+ ", message='" + message + '\'' +
+ ", data=" + data +
+ '}';
+ }
+}
+
diff --git a/YuNan-demo/src/main/java/com/yunan/service/AuthService.java b/YuNan-system-start/src/main/java/com/yunan/service/AuthService.java
similarity index 93%
rename from YuNan-demo/src/main/java/com/yunan/service/AuthService.java
rename to YuNan-system-start/src/main/java/com/yunan/service/AuthService.java
index e293b2a..9f9b6b9 100644
--- a/YuNan-demo/src/main/java/com/yunan/service/AuthService.java
+++ b/YuNan-system-start/src/main/java/com/yunan/service/AuthService.java
@@ -2,7 +2,6 @@ package com.yunan.service;
import com.yunan.dto.RegisterDTO;
-import com.yunan.pojo.User;
import org.springframework.http.ResponseEntity;
import javax.mail.MessagingException;
diff --git a/YuNan-system-start/src/main/java/com/yunan/service/CaptchaService.java b/YuNan-system-start/src/main/java/com/yunan/service/CaptchaService.java
new file mode 100644
index 0000000..fc91503
--- /dev/null
+++ b/YuNan-system-start/src/main/java/com/yunan/service/CaptchaService.java
@@ -0,0 +1,88 @@
+package com.yunan.service;
+
+import com.github.xiaoymin.knife4j.core.util.StrUtil;
+import com.yunan.dto.Captcha;
+import com.yunan.util.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.UUID;
+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 ops = stringRedisTemplate.opsForValue();
+ String text = ops.get("imageCode:" + imageKey);
+ if(StrUtil.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 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;
+ }
+}
diff --git a/YuNan-demo/src/main/java/com/yunan/service/EmailService.java b/YuNan-system-start/src/main/java/com/yunan/service/EmailService.java
similarity index 100%
rename from YuNan-demo/src/main/java/com/yunan/service/EmailService.java
rename to YuNan-system-start/src/main/java/com/yunan/service/EmailService.java
diff --git a/YuNan-demo/src/main/java/com/yunan/service/impl/AuthServiceImpl.java b/YuNan-system-start/src/main/java/com/yunan/service/impl/AuthServiceImpl.java
similarity index 98%
rename from YuNan-demo/src/main/java/com/yunan/service/impl/AuthServiceImpl.java
rename to YuNan-system-start/src/main/java/com/yunan/service/impl/AuthServiceImpl.java
index 8012859..eef98fd 100644
--- a/YuNan-demo/src/main/java/com/yunan/service/impl/AuthServiceImpl.java
+++ b/YuNan-system-start/src/main/java/com/yunan/service/impl/AuthServiceImpl.java
@@ -3,7 +3,7 @@ package com.yunan.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yunan.dto.RegisterDTO;
import com.yunan.mapper.AuthMapper;
-import com.yunan.pojo.User;
+import com.yunan.dto.User;
import com.yunan.response.ErrorResponse;
import com.yunan.service.AuthService;
import org.springframework.http.HttpStatus;
diff --git a/YuNan-system-start/src/main/java/com/yunan/util/CaptchaUtils.java b/YuNan-system-start/src/main/java/com/yunan/util/CaptchaUtils.java
new file mode 100644
index 0000000..705392c
--- /dev/null
+++ b/YuNan-system-start/src/main/java/com/yunan/util/CaptchaUtils.java
@@ -0,0 +1,229 @@
+package com.yunan.util;
+
+import com.yunan.dto.Captcha;
+import org.apache.commons.lang3.RandomUtils;
+
+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.net.URL;
+import java.util.Base64;
+import java.util.Objects;
+import java.util.Random;
+
+public class CaptchaUtils {
+
+ /**
+ * 网络图片地址
+ **/
+ private final static String IMG_URL = "https://loyer.wang/view/ftp/wallpaper/%s.jpg";
+
+ /**
+ * 本地图片地址
+ **/
+ private final static String IMG_PATH = "C:/Users/NanYu/Pictures/ComputerPaper/%s.jpg";
+
+ /**
+ * 入参校验设置默认值
+ **/
+ public static void checkCaptcha(Captcha captcha) {
+ //设置画布宽度默认值
+ if (captcha.getCanvasWidth() == null) {
+ captcha.setCanvasWidth(320);
+ }
+ //设置画布高度默认值
+ if (captcha.getCanvasHeight() == null) {
+ captcha.setCanvasHeight(155);
+ }
+ //设置阻塞块宽度默认值
+ if (captcha.getBlockWidth() == null) {
+ captcha.setBlockWidth(65);
+ }
+ //设置阻塞块高度默认值
+ if (captcha.getBlockHeight() == null) {
+ captcha.setBlockHeight(55);
+ }
+ //设置阻塞块凹凸半径默认值
+ if (captcha.getBlockRadius() == null) {
+ captcha.setBlockRadius(9);
+ }
+ //设置图片来源默认值
+ if (captcha.getPlace() == null) {
+ captcha.setPlace(0);
+ }
+ }
+
+ /**
+ * 获取指定范围内的随机数
+ **/
+ public static int getNonceByRange(int start, int end) {
+ Random random = new Random();
+ return random.nextInt(end - start + 1) + start;
+ }
+
+ /**
+ * 获取验证码资源图
+ **/
+ public static BufferedImage getBufferedImage(Integer place) {
+ try {
+ //随机图片
+// int nonce = getNonceByRange(0, 1000);
+ int nonce = 111;
+
+ //获取网络资源图片
+ if (0 == place) {
+ String imgUrl = String.format(IMG_URL, nonce);
+ URL url = new URL(imgUrl);
+ return ImageIO.read(url.openStream());
+ }
+ //获取本地图片
+ else {
+ String imgPath = String.format(IMG_PATH, nonce);
+ File file = new File(imgPath);
+ return ImageIO.read(file);
+ }
+ } catch (Exception e) {
+ System.out.println("获取拼图资源失败");
+ //异常处理
+ return null;
+ }
+ }
+
+ /**
+ * 调整图片大小
+ **/
+ public static BufferedImage imageResize(BufferedImage bufferedImage, int width, int height) {
+ Image image = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
+ BufferedImage resultImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D graphics2D = resultImage.createGraphics();
+ graphics2D.drawImage(image, 0, 0, null);
+ graphics2D.dispose();
+ return resultImage;
+ }
+
+ /**
+ * 抠图,并生成阻塞块
+ **/
+ public static void cutByTemplate(BufferedImage canvasImage, BufferedImage blockImage, int blockWidth, int blockHeight, int blockRadius, int blockX, int blockY) {
+ BufferedImage waterImage = new BufferedImage(blockWidth, blockHeight, BufferedImage.TYPE_4BYTE_ABGR);
+ //阻塞块的轮廓图
+ int[][] blockData = getBlockData(blockWidth, blockHeight, blockRadius);
+ //创建阻塞块具体形状
+ for (int i = 0; i < blockWidth; i++) {
+ for (int j = 0; j < blockHeight; j++) {
+ try {
+ //原图中对应位置变色处理
+ if (blockData[i][j] == 1) {
+ //背景设置为黑色
+ waterImage.setRGB(i, j, Color.BLACK.getRGB());
+ blockImage.setRGB(i, j, canvasImage.getRGB(blockX + i, blockY + j));
+ //轮廓设置为白色,取带像素和无像素的界点,判断该点是不是临界轮廓点
+ if (blockData[i + 1][j] == 0 || blockData[i][j + 1] == 0 || blockData[i - 1][j] == 0 || blockData[i][j - 1] == 0) {
+ blockImage.setRGB(i, j, Color.WHITE.getRGB());
+ waterImage.setRGB(i, j, Color.WHITE.getRGB());
+ }
+ }
+ //这里把背景设为透明
+ else {
+ blockImage.setRGB(i, j, Color.TRANSLUCENT);
+ waterImage.setRGB(i, j, Color.TRANSLUCENT);
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ //防止数组下标越界异常
+ }
+ }
+ }
+ //在画布上添加阻塞块水印
+ addBlockWatermark(canvasImage, waterImage, blockX, blockY);
+ }
+
+ /**
+ * 构建拼图轮廓轨迹
+ **/
+ private static int[][] getBlockData(int blockWidth, int blockHeight, int blockRadius) {
+ int[][] data = new int[blockWidth][blockHeight];
+ double po = Math.pow(blockRadius, 2);
+ //随机生成两个圆的坐标,在4个方向上 随机找到2个方向添加凸/凹
+ //凸/凹1
+ int face1 = RandomUtils.nextInt(0,4);
+ //凸/凹2
+ int face2;
+ //保证两个凸/凹不在同一位置
+ do {
+ face2 = RandomUtils.nextInt(0,4);
+ } while (face1 == face2);
+ //获取凸/凹起位置坐标
+ int[] circle1 = getCircleCoords(face1, blockWidth, blockHeight, blockRadius);
+ int[] circle2 = getCircleCoords(face2, blockWidth, blockHeight, blockRadius);
+ //随机凸/凹类型
+ int shape = getNonceByRange(0, 1);
+ //圆的标准方程 (x-a)²+(y-b)²=r²,标识圆心(a,b),半径为r的圆
+ //计算需要的小图轮廓,用二维数组来表示,二维数组有两张值,0和1,其中0表示没有颜色,1有颜色
+ for (int i = 0; i < blockWidth; i++) {
+ for (int j = 0; j < blockHeight; j++) {
+ data[i][j] = 0;
+ //创建中间的方形区域
+ if ((i >= blockRadius && i <= blockWidth - blockRadius && j >= blockRadius && j <= blockHeight - blockRadius)) {
+ data[i][j] = 1;
+ }
+ double d1 = Math.pow(i - Objects.requireNonNull(circle1)[0], 2) + Math.pow(j - circle1[1], 2);
+ double d2 = Math.pow(i - Objects.requireNonNull(circle2)[0], 2) + Math.pow(j - circle2[1], 2);
+ //创建两个凸/凹
+ if (d1 <= po || d2 <= po) {
+ data[i][j] = shape;
+ }
+ }
+ }
+ return data;
+ }
+ /**
+ * 根据朝向获取圆心坐标
+ */
+ private static int[] getCircleCoords(int face, int blockWidth, int blockHeight, int blockRadius) {
+ //上
+ if (0 == face) {
+ return new int[]{blockWidth / 2 - 1, blockRadius};
+ }
+ //左
+ else if (1 == face) {
+ return new int[]{blockRadius, blockHeight / 2 - 1};
+ }
+ //下
+ else if (2 == face) {
+ return new int[]{blockWidth / 2 - 1, blockHeight - blockRadius - 1};
+ }
+ //右
+ else if (3 == face) {
+ return new int[]{blockWidth - blockRadius - 1, blockHeight / 2 - 1};
+ }
+ return null;
+ }
+ /**
+ * 在画布上添加阻塞块水印
+ */
+ private static void addBlockWatermark(BufferedImage canvasImage, BufferedImage blockImage, int x, int y) {
+ Graphics2D graphics2D = canvasImage.createGraphics();
+ graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.8f));
+ graphics2D.drawImage(blockImage, x, y, null);
+ graphics2D.dispose();
+ }
+ /**
+ * BufferedImage转BASE64
+ */
+ public static String toBase64(BufferedImage bufferedImage, String type) {
+ try {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ ImageIO.write(bufferedImage, type, byteArrayOutputStream);
+ String base64 = Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());
+ return String.format("data:image/%s;base64,%s", type, base64);
+ } catch (IOException e) {
+ System.out.println("图片资源转换BASE64失败");
+ //异常处理
+ return null;
+ }
+ }
+}
+
diff --git a/YuNan-demo/src/main/java/com/yunan/util/RedisUtils.java b/YuNan-system-start/src/main/java/com/yunan/util/RedisUtils.java
similarity index 100%
rename from YuNan-demo/src/main/java/com/yunan/util/RedisUtils.java
rename to YuNan-system-start/src/main/java/com/yunan/util/RedisUtils.java
diff --git a/YuNan-demo/src/main/java/com/yunan/util/VerificationCodeUtils.java b/YuNan-system-start/src/main/java/com/yunan/util/VerificationCodeUtils.java
similarity index 100%
rename from YuNan-demo/src/main/java/com/yunan/util/VerificationCodeUtils.java
rename to YuNan-system-start/src/main/java/com/yunan/util/VerificationCodeUtils.java
diff --git a/YuNan-demo/src/main/resources/application.yml b/YuNan-system-start/src/main/resources/application.yml
similarity index 99%
rename from YuNan-demo/src/main/resources/application.yml
rename to YuNan-system-start/src/main/resources/application.yml
index 62ba5d0..51c86a0 100644
--- a/YuNan-demo/src/main/resources/application.yml
+++ b/YuNan-system-start/src/main/resources/application.yml
@@ -53,3 +53,6 @@ server:
logging:
level:
org.springframework.boot.context.web: DEBUG
+
+
+
diff --git a/YuNan-demo/src/test/java/com/yunan/YuNanDemoApplicationTests.java b/YuNan-system-start/src/test/java/com/yunan/YuNanDemoApplicationTests.java
similarity index 76%
rename from YuNan-demo/src/test/java/com/yunan/YuNanDemoApplicationTests.java
rename to YuNan-system-start/src/test/java/com/yunan/YuNanDemoApplicationTests.java
index 6c6b8d7..1a06e2a 100644
--- a/YuNan-demo/src/test/java/com/yunan/YuNanDemoApplicationTests.java
+++ b/YuNan-system-start/src/test/java/com/yunan/YuNanDemoApplicationTests.java
@@ -1,9 +1,9 @@
package com.yunan;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.context.SpringBootTest;
-@SpringBootTest
+import org.springframework.boot.test.context.SpringBootTest;
+import org.testng.annotations.Test;
+
class YuNanDemoApplicationTests {
@Test
diff --git a/pom.xml b/pom.xml
index fd225f0..f15d0e1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
- YuNan-demo
+ YuNan-system-start
@@ -111,6 +111,8 @@
org.apache.commons
commons-pool2
+
+