1.首先是生成验证码
2.将生产的验证码保存在缓存中,只保存1-2分钟
缓存使用的是:ExpiringMap(一个轻量的Java缓存方式)
<dependency>
<groupId>net.jodah</groupId>
<artifactId>expiringmap</artifactId>
<version>0.5.8</version>
</dependency>
验证码的工具类:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.Random;
/*对图片进行处理的类和方法*/
public class VerifyCode {
public static String drawRandomText(int width,int height, BufferedImage verifyImg) {
Graphics2D graphics = (Graphics2D)verifyImg.getGraphics();
graphics.setColor(Color.WHITE);//设置画笔颜色-验证码背景色
graphics.fillRect(0, 0, width, height);//填充背景
graphics.setFont(new Font("微软雅黑", Font.BOLD, 40));
// //数字和大小写字母的组合
// String baseNumLetter= "123456789abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
//数字和小写字母的组合
String baseNumLetter= "123456789abcdefghijklmnopqrstuvwxyz";
// //纯数字组合
// String baseNumLetter= "123456789";
StringBuffer sBuffer = new StringBuffer();
int x = 10; //旋转原点的 x 坐标
String ch = "";
Random random = new Random();
for(int i = 0;i < 4;i++){
graphics.setColor(getRandomColor());
//设置字体旋转角度
int degree = random.nextInt() % 20; //角度小于20度
int dot = random.nextInt(baseNumLetter.length());
ch = baseNumLetter.charAt(dot) + "";
sBuffer.append(ch);
//正向旋转
graphics.rotate(degree * Math.PI / 180, x, 45);
graphics.drawString(ch, x, 45);
//反向旋转
graphics.rotate(-degree * Math.PI / 180, x, 45);
x += 48;
}
//画干扰线
for (int i = 0; i <3; i++) {
// 设置随机颜色
graphics.setColor(getRandomColor());
// 随机画线
graphics.drawLine(random.nextInt(width), random.nextInt(height),
random.nextInt(width), random.nextInt(height));
}
//添加噪点
for(int i=0;i<20;i++){
int x1 = random.nextInt(width);
int y1 = random.nextInt(height);
graphics.setColor(getRandomColor());
graphics.fillRect(x1, y1, 2,2);
}
return sBuffer.toString();
}
/**
* 随机取色
*/
private static Color getRandomColor() {
Random ran = new Random();
Color color = new Color(ran.nextInt(256),
ran.nextInt(256), ran.nextInt(256));
return color;
}
}
验证码接口:
import com.sws.nlflow.portal.util.ExpiringMap;
import com.sws.nlflow.portal.util.VerifyCode;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* 验证码处理接口
*/
@Slf4j
@Controller
@RequestMapping("/api")
public class VerifyCodeController {
@RequestMapping("/getVerifyCode")
public void getVerificationCode(HttpServletResponse response, HttpServletRequest request) {
try {
int width = 200;
int height = 69;
BufferedImage verifyImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//生成对应宽高的初始图片
//功能是生成验证码字符并加上噪点,干扰线,返回值为验证码字符
String randomText = VerifyCode.drawRandomText(width, height, verifyImg);
// request.getSession().setAttribute("verifyCode", randomText);
//获取ExpiringMap,将验证码保存在此处
net.jodah.expiringmap.ExpiringMap<String, String> VerifyCodemap = ExpiringMap.map;
VerifyCodemap.put(randomText, randomText);
response.setContentType("image/png");//必须设置响应内容类型为图片,否则前台不识别
OutputStream os = response.getOutputStream(); //获取文件输出流
ImageIO.write(verifyImg, "png", os);//输出图片流
os.flush();
os.close();//关闭流
} catch (IOException e) {
log.error(e.getMessage());
e.printStackTrace();
}
}
}
缓存工具类:
import java.io.Serializable;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import net.jodah.expiringmap.ExpirationPolicy;
/**
* @author qushen
* @create 2022/8/16 10:37
*/
@Slf4j
public class ExpiringMap implements Serializable {
/**
*
* maxSize:map的最大长度,添加第1001个entry时,会导致第1个马上过期(即使没到过期时间)
* expiration:过期时间和过期单位,设置过期时间,则永久有效.
* expirationPolicy:过期策略的使用
* CREATED: 在每次更新元素时,过期倒计时清零
* ACCESSED: 在每次访问元素时,过期倒计时清零
*
* variableExpiration:允许更新过期时间值,如果不设置variableExpiration
* 不允许更改过期时间,一旦执行更改过期时间的操作则会抛出UnsupportedOperationException异常
* expirationListener:同步过期提醒
* asyncExpirationListener:异步过期提醒
* entryLoader:懒加载,调用get方法时若key不存在创建默认value
*
*/
public static net.jodah.expiringmap.ExpiringMap<String, String> map = net.jodah.expiringmap.ExpiringMap.builder()
//设置过期时间
.expiration(120, TimeUnit.SECONDS)
//设置过期协议
.expirationPolicy(ExpirationPolicy.ACCESSED)
.variableExpiration()
.build();
}
登录时候的验证方法:
//传入参数: VerifyCode
net.jodah.expiringmap.ExpiringMap<String, String> VerifyCodemap = ExpiringMap.map;
if(!VerifyCodemap.containsKey(VerifyCode)){
return new Response(Integer.valueOf(1), "验证码不正确!");
}