验证码

SpringBoot 之 kaptcha

kaptcha,一款谷歌出品的验证码工具

引入kaptcha

1
2
3
4
5
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>

配置验证码样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import com.google.code.kaptcha.util.Config;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

@Configuration
public class KaptchaConfig {
@Bean
public DefaultKaptcha getDefaultKaptcha() {
DefaultKaptcha captchaProducer = new DefaultKaptcha();
Properties properties = new Properties();
properties.setProperty("kaptcha.border", "yes");
properties.setProperty("kaptcha.border.color", "44,156,250");
properties.setProperty("kaptcha.textproducer.font.color", "black");
properties.setProperty("kaptcha.image.width", "110");
properties.setProperty("kaptcha.image.height", "30");
properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.ShadowGimpy");
properties.setProperty("kaptcha.textproducer.font.size", "24");
properties.setProperty("kaptcha.session.key", "code");
properties.setProperty("kaptcha.textproducer.char.length", "4");
properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
Config config = new Config(properties);
captchaProducer.setConfig(config);
return captchaProducer;
}
}

其他配置项

Constant 描写叙述 默认值
kaptcha.border 图片边框,合法值:yes , no yes
kaptcha.border.color 边框颜色,合法值: r,g,b (and optional alpha) 或者 white,black,blue. black
kaptcha.border.thickness 边框厚度。合法值:>0 1
kaptcha.image.width 图片宽 200
kaptcha.image.height 图片高 50
kaptcha.producer.impl 图片实现类 com.google.code.kaptcha.impl.DefaultKaptcha
kaptcha.textproducer.impl 文本实现类 com.google.code.kaptcha.text.impl.DefaultTextCreator
kaptcha.textproducer.char.string 文本集合,验证码值从此集合中获取 abcde2345678gfynmnpwx
kaptcha.textproducer.char.length 验证码长度 5
kaptcha.textproducer.font.names 字体 Arial, Courier
kaptcha.textproducer.font.size 字体大小 40px.
kaptcha.textproducer.font.color 字体颜色,合法值: r,g,b 或者 white,black,blue. black
kaptcha.textproducer.char.space 文字间隔 2
kaptcha.noise.impl 干扰实现类 com.google.code.kaptcha.impl.DefaultNoise
kaptcha.noise.color 干扰颜色。合法值: r,g,b 或者 white,black,blue. black
kaptcha.background.impl 背景实现类 com.google.code.kaptcha.impl.DefaultBackground
kaptcha.background.clear.from 背景颜色渐变,開始颜色 light grey
kaptcha.background.clear.to 背景颜色渐变。结束颜色 white
kaptcha.word.impl 文字渲染器 com.google.code.kaptcha.text.impl.DefaultWordRenderer
kaptcha.session.key session key KAPTCHA_SESSION_KEY
kaptcha.session.date session date KAPTCHA_SESSION_DATE
kaptcha.obscurificator.impl 图片样式:水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy com.google.code.kaptcha.impl.WaterRipple

controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@RestController
@RequestMapping("/captcha")
public class KaptchaController {
@Autowired
DefaultKaptcha defaultKaptcha;

// 生成验证码
@RequestMapping(method = RequestMethod.GET)
public String createKaptcha(final HttpServletRequest request, final HttpServletResponse response) throws Exception {

HttpSession session = request.getSession();
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
response.setHeader("Pragma", "no-cache");
response.setContentType("image/jpeg");

String capText = defaultKaptcha.createText();
session.setAttribute(Const.KAPTCHA_SESSION_KEY, capText);
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
BufferedImage img = defaultKaptcha.createImage(capText);
ImageIO.write(img, "jpg", out);

BASE64Encoder encoder = new BASE64Encoder();
String base64 = encoder.encode(out.toByteArray()).trim();
String base64Format = "data:image/png;base64," + base64.replaceAll("\n", "").replaceAll("\r", "");
return base64Format;
} catch (Exception e) {
throw new Exception(e.getMessage(), e);
}
}

// 校验验证码
@RequestMapping(value = "/verify", method = RequestMethod.GET)
public Boolean verifyKaptcha(@RequestParam String captcha, final HttpServletRequest request) {
boolean isCaptchaPassed = KaptchaUtil.checkVerifyCode(captcha, request);
return isCaptchaPassed;
}
}
1
2
3
4
5
6
public class KaptchaUtil {
public static boolean checkVerifyCode(String captchaInput, final HttpServletRequest request) {
String captchaExpected = (String) request.getSession().getAttribute(Const.KAPTCHA_SESSION_KEY);
return captchaInput != null && captchaInput.equals(captchaExpected);
}
}

前端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<img
className="image"
alt="点击更换"
onClick={this.onRefreshCode}
src=""
ref={(dom) => { this.codeImg = dom; }}
/>

onRefreshCode = () => {
this.props.getCode().then((data) => {
if (data) {
this.codeImg.src = data; // src = data:image/png;base64图片
}
});
};

调取校验接口(captcha/verify)时,注意跨域携带session(后端用其存储验证码)

1
2
3
4
5
ajax:
xhrFields: {withCredentials: true}

fetch:
credentials: 'include'

-------------Keep It Simple Stupid-------------
0%