feat: 短信验证码和滑动图片验证
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
package com.schisandra.auth.application.controller;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.util.Base64;
|
||||
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/ReactRotateCaptcha/")
|
||||
@Slf4j
|
||||
public class ReactRotateCaptchaController {
|
||||
@PostMapping (value = "get", produces = MediaType.IMAGE_PNG_VALUE)
|
||||
public ResponseEntity<String> 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求图片地址, 返回的结果进行base64编码
|
||||
* @param imgUrl 图片地址
|
||||
* @return
|
||||
*/
|
||||
// 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;
|
||||
// }
|
||||
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
package com.schisandra.auth.application.controller;
|
||||
|
||||
|
||||
import com.schisandra.auth.common.utils.RedisUtils;
|
||||
import com.schisandra.auth.common.utils.SmsCodeUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.sms4j.api.SmsBlend;
|
||||
import org.dromara.sms4j.api.entity.SmsResponse;
|
||||
import org.dromara.sms4j.core.factory.SmsFactory;
|
||||
import org.dromara.sms4j.provider.enumerate.SupplierType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/sms/")
|
||||
@Slf4j
|
||||
public class SmsController {
|
||||
@Autowired
|
||||
private RedisUtils redisUtils;
|
||||
private final SmsBlend aliSms = SmsFactory.createSmsBlend(SupplierType.ALIBABA);
|
||||
|
||||
@GetMapping("/send")
|
||||
public SmsResponse send(String phone, String templateId) {
|
||||
return aliSms.sendMessage(phone, templateId, new LinkedHashMap<>());
|
||||
}
|
||||
|
||||
@GetMapping("/sendByTemplate")
|
||||
public SmsResponse sendByTemplate(String phone) {
|
||||
// SmsBlend smsBlend = SmsFactory.getSmsBlend("alibaba");
|
||||
String code = SmsCodeUtils.generateValidateCode(4).toString();
|
||||
// redisUtils.cacheValue( phone, code, 60);
|
||||
|
||||
SmsResponse smsResponse=aliSms.sendMessage(phone, code);
|
||||
if (smsResponse.isSuccess()){
|
||||
redisUtils.cacheValue( phone, code, 60);
|
||||
return smsResponse;
|
||||
}else {
|
||||
return smsResponse;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
package com.schisandra.auth.common.utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.ValueOperations;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author luft-mensch
|
||||
*/
|
||||
@Component
|
||||
public class RedisUtils {
|
||||
|
||||
@Resource
|
||||
private RedisTemplate<String,Object> redisTemplate;
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
|
||||
public boolean cacheValue(String key, Object value, long time) {
|
||||
try {
|
||||
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
|
||||
valueOperations.set(key, value);
|
||||
if (time > 0) {
|
||||
// 如果有设置超时时间的话
|
||||
redisTemplate.expire(key, time, TimeUnit.SECONDS);
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
logger.error("缓存[" + key + "]失败, value[" + value + "] " + e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean cacheValue(String key, Object value) {
|
||||
return cacheValue(key, value, -1);
|
||||
}
|
||||
|
||||
|
||||
public boolean containsKey(String key) {
|
||||
try {
|
||||
return redisTemplate.hasKey(key);
|
||||
} catch (Throwable e) {
|
||||
logger.error("判断缓存是否存在时失败key[" + key + "]", "err[" + e.getMessage() + "]");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object getValue(String key) {
|
||||
try {
|
||||
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
|
||||
return valueOperations.get(key);
|
||||
} catch (Throwable e) {
|
||||
logger.error("获取缓存时失败key[" + key + "]", "err[" + e.getMessage() + "]");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public boolean removeValue(String key) {
|
||||
try {
|
||||
redisTemplate.delete(key);
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
logger.error("移除缓存时失败key[" + key + "]", "err[" + e.getMessage() + "]");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean removeKeys(String pattern) {
|
||||
try {
|
||||
Set<String> keySet = redisTemplate.keys(pattern + "*");
|
||||
redisTemplate.delete(keySet);
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
logger.error("移除key[" + pattern + "]前缀的缓存时失败", "err[" + e.getMessage() + "]");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
package com.schisandra.auth.common.utils;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class SmsCodeUtils {
|
||||
public static Integer generateValidateCode(int length){
|
||||
Integer code =null;
|
||||
|
||||
//长度为4
|
||||
if(length == 4){
|
||||
//生成随机数,最大为9999
|
||||
code = new Random().nextInt(9999);
|
||||
if(code < 1000){
|
||||
//保证随机数为4位数字
|
||||
code = code + 1000;
|
||||
}
|
||||
//长度为6
|
||||
}else if(length == 6){
|
||||
//生成随机数,最大为999999
|
||||
code = new Random().nextInt(999999);
|
||||
if(code < 100000){
|
||||
//保证随机数为6位数字
|
||||
code = code + 100000;
|
||||
}
|
||||
//其他情况
|
||||
}else{
|
||||
throw new RuntimeException("只能生成4位或6位数字验证码");
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
}
|
@@ -70,37 +70,30 @@ sa-token:
|
||||
is-log: true
|
||||
token-prefix: schisandra
|
||||
|
||||
#sms:
|
||||
# # 标注从yml读取配置
|
||||
# config-type: yaml
|
||||
# blends:
|
||||
# # 自定义的标识,也就是configId这里可以是任意值(最好不要是中文)
|
||||
# tx1:
|
||||
# #厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
|
||||
# supplier: tencent
|
||||
# #您的accessKey
|
||||
# access-key-id: 您的accessKey
|
||||
# #您的accessKeySecret
|
||||
# access-key-secret: 您的accessKeySecret
|
||||
# #您的短信签名
|
||||
# signature: 您的短信签名
|
||||
# #模板ID 非必须配置,如果使用sendMessage的快速发送需此配置
|
||||
# template-id: xxxxxxxx
|
||||
# #您的sdkAppId
|
||||
# sdk-app-id: 您的sdkAppId
|
||||
# # 自定义的标识,也就是configId这里可以是任意值(最好不要是中文)
|
||||
# tx2:
|
||||
# #厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
|
||||
# supplier: tencent
|
||||
# #您的accessKey
|
||||
# access-key-id: 您的accessKey
|
||||
# #您的accessKeySecret
|
||||
# access-key-secret: 您的accessKeySecret
|
||||
# #您的短信签名
|
||||
# signature: 您的短信签名
|
||||
# #模板ID 非必须配置,如果使用sendMessage的快速发送需此配置
|
||||
# template-id: xxxxxxxx
|
||||
# #您的sdkAppId
|
||||
# sdk-app-id: 您的sdkAppId
|
||||
sms:
|
||||
# 标注从yml读取配置0
|
||||
# 自定义的标识,也就是configId这里可以是任意值(最好不要是中文)
|
||||
alibaba:
|
||||
#厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
|
||||
supplier: alibaba
|
||||
#您的accessKey
|
||||
access-key-id: LTAI5tDy2edL9LhW43rnus69
|
||||
#您的accessKeySecret
|
||||
access-key-secret: YWp44dcFrBICrjZgqvJBE7ZHArZfIP
|
||||
#您的短信签名
|
||||
signature: 阿里云短信测试
|
||||
#模板ID 非必须配置,如果使用sendMessage的快速发送需此配置
|
||||
template-id: SMS_154950909
|
||||
template-name: code
|
||||
#您的sdkAppId
|
||||
sdk-app-id: sms
|
||||
requestUrl: dysmsapi.aliyuncs.com
|
||||
# # 接口方法默认为 SendSms 如无特殊改变可以不用设置
|
||||
# action: SendSms
|
||||
# # 接口版本号默认为 2017-05-25 如无特殊改变可以不用设置
|
||||
# version: 2017-05-25
|
||||
# # 地域信息默认为 cn-hangzhou 如无特殊改变可以不用设置
|
||||
# regionId: cn-hangzhou
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user