导入依赖
<dependency>
<groupId>com.github.axet</groupId>
<artifactId>kaptcha</artifactId>
<version>0.0.9</version>
</dependency>
添加验证码的配置信息
kaptcha.properties
# 验证码配置
kaptcha.border=no
kaptcha.border.color=105,179,90
kaptcha.image.width=100
kaptcha.image.height=45
kaptcha.session.key=code
kaptcha.textproducer.font.color=blue
kaptcha.textproducer.font.size=35
kaptcha.textproducer.char.length=4
kaptcha.textproducer.font.names=\u5B8B\u4F53,\u6977\u4F53,\u5FAE\u8F6F\u96C5\u9ED1
验证码过期时间
CaptchaImageModel
package com.admin.model;
import java.time.LocalDateTime;
/**
* @version 1.0
* @Author 张云飞
* @Date 2021/10/6 0006 15:20
* @注释 验证码过期时间
*/
public class CaptchaImageModel {
private String code;
private LocalDateTime expireTime;
public CaptchaImageModel(String code, int expireAfterSeconds){
this.code = code;
this.expireTime = LocalDateTime.now().plusSeconds(expireAfterSeconds);
}
public String getCode() {
return code;
}
/**
* 验证码是否失效
* @return
*/
public boolean isExpired(){
return LocalDateTime.now().isAfter(expireTime);
}
}
controller层
package com.admin.controller;
import com.admin.model.CaptchaImageModel;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;
/**
* @version 1.0
* @Author 张云飞
* @Date 2021/10/6 0006 15:15
* @注释
*/
@RestController
public class CaptchaController {
@Resource
private DefaultKaptcha defaultKaptcha;
@RequestMapping("/image")
public void kaptcha(HttpSession session, HttpServletResponse response) throws IOException {
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 并设置2分钟后过期
session.setAttribute("captcha_key", new CaptchaImageModel(capText, 2 * 60));
ServletOutputStream out = response.getOutputStream();
BufferedImage bufferedImage = defaultKaptcha.createImage(capText);
ImageIO.write(bufferedImage, "jpg", out);
//刷新
out.flush();
}
}
验证码校验使用过滤器来完成,在配置类中加入过滤器
CaptchaCodeFilter
package com.admin.filters;
import com.admin.model.CaptchaImageModel;
import com.admin.model.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.session.SessionAuthenticationException;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Objects;
/**
* @version 1.0
* @Author 张云飞
* @Date 2021/10/6 0006 15:42
* @注释
*/
@Component
public class CaptchaCodeFilter extends OncePerRequestFilter {
private static ObjectMapper objectMapper=new ObjectMapper();
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
//只有在登录请求时才有验证码过滤操作
if (StringUtils.equals("/login",request.getRequestURI()) && StringUtils.equalsIgnoreCase(request.getMethod(),"post")){
//校验登录验证码是否正确
try {
this.validate(new ServletWebRequest(request));
} catch (AuthenticationException e) {
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(objectMapper.writeValueAsString(
Result.error("验证码错误")
));
return;
}
}
filterChain.doFilter(request,response);
}
private void validate(ServletWebRequest request) throws ServletRequestBindingException {
HttpSession session = request.getRequest().getSession();
//获取请求中参数值
String codeInRequest = ServletRequestUtils.getStringParameter(request.getRequest(), "captchaCode");
if (StringUtils.isEmpty(codeInRequest)){
throw new SessionAuthenticationException("验证码不能为空");
}
//拿到图片的session
CaptchaImageModel codeInSession= (CaptchaImageModel) session.getAttribute("captcha_key");
if (Objects.isNull(codeInSession)){
throw new SessionAuthenticationException("验证码不存在");
}
//判断过期
if (codeInSession.isExpired()){
throw new SessionAuthenticationException("验证码过期");
}
//判断验证码是否正确
if (!(StringUtils.equals(codeInSession.getCode(),codeInRequest))){
throw new SessionAuthenticationException("验证码不匹配");
}
}
}