添加验证码
添加依赖
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
传统web开发
前后端分离
创建验证码的配置
@Configuration
public class KaptchaConfiguration {
@Bean
public Producer kaptcha() {
// 创建一个新的Properties对象,用于存储Kaptcha的配置
Properties properties = new Properties();
// 设置验证码图片的宽度为150像素
properties.setProperty("kaptcha.image.width", "150");
// 设置验证码图片的高度为50像素
properties.setProperty("kaptcha.image.height", "50");
// 设置验证码的字符集为数字0-9
properties.setProperty("kaptcha.textproducer.char.string", "0123456789");
// 设置验证码的长度为4个字符
properties.setProperty("kaptcha.textproducer.char.length", "4");
// 设置验证码的字体大小为40
properties.setProperty("kaptcha.textproducer.font.size", "40");
// 设置验证码的噪声实现类为NoNoise,即不产生噪声
properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.NoNoise");
// 设置验证码的干扰实现类为ShadowGimpy,即产生一个阴影效果
properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.ShadowGimpy");
// 设置验证码的背景颜色从白色渐变到白色(即纯白色背景)
properties.setProperty("kaptcha.background.clear.from", "white");
properties.setProperty("kaptcha.background.clear.to", "white");
// 设置验证码的字体颜色为黑色
properties.setProperty("kaptcha.textproducer.font.color", "black");
// 设置验证码的字符间距为5
properties.setProperty("kaptcha.textproducer.char.space", "5");
// 设置验证码的字体为Arial和Courier
properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier");
// 设置验证码的边框为无边框
properties.setProperty("kaptcha.border", "no");
// 设置验证码的边框颜色为黑色(实际上由于上一行设置了无边框,所以这一行设置的边框颜色不会生效)
properties.setProperty("kaptcha.border.color", "black");
// 创建一个DefaultKaptcha对象
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
// 将上面设置的属性应用到DefaultKaptcha对象
defaultKaptcha.setConfig(new Config(properties));
// 返回配置好的DefaultKaptcha对象
return defaultKaptcha;
}
}
创建生成验证码的controller:
@Slf4j
@RestController
@RequestMapping("/")
@RequiredArgsConstructor
public class HelloController {
private final Producer producer;
@GetMapping("/verification-code")
public String vc(HttpSession session) throws IOException {
// 生成验证码
String text = producer.createText();
// 将验证码放入到session或者redis中
session.setAttribute("code", text);
// 生成图片
BufferedImage image = producer.createImage(text);
// 将图片转换为base64
FastByteArrayOutputStream fastByteArrayOutputStream = new FastByteArrayOutputStream();
ImageIO.write(image, "jpg", fastByteArrayOutputStream);
return Base64.getEncoder().encodeToString(fastByteArrayOutputStream.toByteArray());
}
}
在LoginFilter
中添加对验证码的校验逻辑:
@EqualsAndHashCode(callSuper = true)
@Data
@Slf4j
public class LoginFilter extends UsernamePasswordAuthenticationFilter {
public static final String SPRING_SECURITY_FORM_CODE_KEY = "code";
private String codeParameter = SPRING_SECURITY_FORM_CODE_KEY;
@SneakyThrows
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
if (!request.getMethod().equals(HttpMethod.POST.name())) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
// 仅支持json格式的数据
if (!request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)) {
throw new AuthenticationServiceException("Authentication contentType not supported: " + request.getContentType());
}
ObjectMapper objectMapper = new ObjectMapper();
Map<String, String> map = objectMapper.readValue(request.getInputStream(), new TypeReference<>() {
});
// 获取请求中的验证码
String reqCode = map.get(getCodeParameter());
String username = map.get(getUsernameParameter());
String password = map.get(getPasswordParameter());
// session 验证码
String sessionCode = (String) request.getSession().getAttribute(getCodeParameter());
if (reqCode == null || !reqCode.equals(sessionCode)) {
throw new AuthenticationServiceException("验证码错误");
}
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
}
最后更新于
这有帮助吗?