一、验证码简介
使用验证码的作用:防止恶意破解密码、刷票、论坛灌水、刷页、恶意注册、登录
不使用验证码的问题通过程序随机生成由大写字母、小写字母、数字、汉字组成的字符串
- 优点:生成方便,识别难易程度可调节
- 缺点:识别度不好掌握,识别度高容易被程序识别,识别度低用户体验较差
使用Java实现随机字符串验证码步骤
- 创建画板:new BufferedImage()
- 创建画笔:画板.getGraphics()
- 随机生成内容:不同颜色的字符
- 绘制内容:画笔.drawString()
存为图片发送:ImageIO.write(画板,图片类型,输出流) ```java @Component @Slf4j public class RandomCodeUtil { private final Random random = new Random();
public String randCode(int len) { if (len < 4) {
len = 4;
} // 生成字符串 StringBuilder code = new StringBuilder(); for (int i = 0; i < len; i++) {
String str = "1234567890abcdefghijklmnopqrstuvwxyz";
code.append(str.charAt(random.nextInt(str.length())));
} return code.toString(); }
public Color randColor() {
int r = random.nextInt(256);
int g = random.nextInt(256);
int b = random.nextInt(256);
return new Color(r, g, b);
}
public void createCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 创建画板
int height = 60;
int width = 140;
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
// 创建画笔
Graphics2D pen = img.createGraphics();
// 生成随机字符串
String code = randCode(4);
log.info(code);
request.getSession().setAttribute("randomCode", code);
pen.fillRect(0, 0, width, height);
int fontSize = 14;
pen.setFont(new Font("微软雅黑", Font.BOLD, fontSize + random.nextInt(5)));
for (int i = 0; i < code.length(); i++) {
pen.setColor(randColor());
pen.drawString(code.charAt(i) + "", 20 + i * fontSize, (fontSize + height) / 2 + random.nextInt(5));
}
ServletOutputStream out = response.getOutputStream();
ImageIO.write(img,"png", out);
out.flush();
out.close();
}
}
- controller实现
```java
@GetMapping("/randomCode")
private void randomCode() {
try {
randomCodeUtil.createCode(request, response);
} catch (IOException e) {
e.printStackTrace();
}
}
@GetMapping("/checkRandomCode")
private String checkRandomCode(String code) {
String saveCode = (String) request.getSession().getAttribute("randomCode");
log.info("randomCode");
if (saveCode.equalsIgnoreCase(code)) {
log.info("验证码正确");
return "验证码正确";
} else {
log.info("验证码错误");
return "验证码错误";
}
}
三、算数验证码
@Component
@Slf4j
public class RandomCodeUtil {
private final Random random = new Random();
public String randCode(int len) {
if (len < 4) {
len = 4;
}
// 生成字符串
StringBuilder code = new StringBuilder();
for (int i = 0; i < len; i++) {
String str = "1234567890abcdefghijklmnopqrstuvwxyz";
code.append(str.charAt(random.nextInt(str.length())));
}
return code.toString();
}
public Color randColor() {
int r = random.nextInt(256);
int g = random.nextInt(256);
int b = random.nextInt(256);
return new Color(r, g, b);
}
public void createCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 创建画板
int height = 60;
int width = 140;
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
// 创建画笔
Graphics2D pen = img.createGraphics();
// 生成随机字符串
String code = randCode(4);
log.info(code);
request.getSession().setAttribute("randomCode", code);
pen.fillRect(0, 0, width, height);
int fontSize = 14;
pen.setFont(new Font("微软雅黑", Font.BOLD, fontSize + random.nextInt(5)));
for (int i = 0; i < code.length(); i++) {
pen.setColor(randColor());
pen.drawString(code.charAt(i) + "", 20 + i * fontSize, (fontSize + height) / 2 + random.nextInt(5));
}
ServletOutputStream out = response.getOutputStream();
ImageIO.write(img,"png", out);
out.flush();
out.close();
}
}
controller实现
@GetMapping("/mathCode")
private void mathCode() {
try {
mathCodeUtil.createCode(request, response);
} catch (IOException e) {
log.error("生成验证码错误");
}
}
@GetMapping("/checkMathCode")
private String checkMathCode(String code) {
int saveCode = (Integer) request.getSession().getAttribute("mathCode");
log.info(String.valueOf(saveCode));
int sendCode = Integer.parseInt(code);
if (saveCode == sendCode) {
log.info("验证码正确");
return "验证码正确";
} else {
log.info("验证码错误");
return "验证码错误";
}
}
四、kaptcha框架验证码
优点:实用,根据帮助文档进行配置即可,不用考虑实现细节
添加pom依赖
<dependency>
<groupId>com.github.axet</groupId>
<artifactId>kaptcha</artifactId>
<version>0.0.9</version>
</dependency>
实现配置类
@Configuration
public class KaptchaConfig {
@Bean
public DefaultKaptcha producer(){
Properties properties = new Properties();
properties.put("kaptcha.barber","no");
properties.put("kaptcha.textproducer.font.color","black");
properties.put("kaptcha.textproducer.char.space","5");
Config config = new Config(properties);
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
写controller接口 ```java @GetMapping(“/captchCode”) private void captchCode() { response.setHeader(“Cache-Control”, “no-store”); response.setContentType(“image/jpeg”); // 文字验证码 String text = producer.createText(); log.info(text); request.getSession().setAttribute(“captchCode”, text); // 图片验证码 BufferedImage image = producer.createImage(text); // 保存验证码到session request.getSession().setAttribute(Constants.KAPTCHA_SESSION_CONFIG_KEY, text); ServletOutputStream outputStream = null; try {
outputStream = response.getOutputStream();
ImageIO.write(image, "jpg", outputStream);
} catch (IOException e) {
e.printStackTrace();
} IOUtils.closeQuietly(outputStream); }
@GetMapping("/checkCapchaCode")
private String checkCapchaCode(String code) {
String saveCode = (String) request.getSession().getAttribute("captchCode");
log.info(saveCode);
if (saveCode.equalsIgnoreCase(code)) {
log.info("验证码正确");
return "验证码正确";
} else {
log.info("验证码错误");
return "验证码错误";
}
}