@GetMapping("getImageVerifyCode")
public Map getImageVerifyCode(HttpServletRequest request, HttpServletResponse response)throws IOException {
//定义图形验证码的长、宽、验证码字符数、干扰线宽度
ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(155, 45, 5, 4);
//图形验证码写出,可以写出到文件,也可以写出到流
String verifyCode = captcha.getCode();
request.getSession().setAttribute("verifyCode",verifyCode);
Map map = new HashMap<>(3);
map.put("data",captcha.getImageBase64Data());
map.put("code",0);
map.put("msg","success");
return map;
}
当然,网关处得把这个地址加入白名单。
还有认证服务中security配置也加入过滤
.antMatchers("/oauth/getImageVerifyCode").permitAll()
/**
* @author cmy
* @date 2023/5/6 11:37
*/
@Component
@Setter
public class CaptchaFilter extends OncePerRequestFilter {
private String processUrl = "/oauth/token";
AuthenticationFailureHandler failureHandler;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if(processUrl.equals(request.getRequestURI()) && StrUtil.equalsAnyIgnoreCase(request.getMethod(), "post")){
try {
validate(request);
} catch (ValidateCodeException e) {
failureHandler.onAuthenticationFailure(request, response, e);
return;
}
}
filterChain.doFilter(request, response);
}
private void validate(HttpServletRequest request) throws ValidateCodeException{
String imageCodeInSession = request.getSession().getAttribute("verifyCode").toString();
String imageCode = request.getHeader("imageCode");
System.out.println("imageCodeInSession = " + imageCodeInSession);
System.out.println("imageCode = " + imageCode);
if(StrUtil.isEmpty(imageCodeInSession)){
throw new ValidateCodeException("验证码不存在,请重新获取");
}
if (StrUtil.isEmpty(imageCode)) {
throw new ValidateCodeException("验证码不能为空,请输入验证码");
}
if(!imageCode.equals(imageCodeInSession)){
throw new ValidateCodeException("验证码不匹配");
}
request.getSession().removeAttribute("verifyCode");
}
}
这边是把验证码放到session里面,目前认证服务没有集群,后期如果集群的话,可以放入Redis
/**
* @author cmy
* @date 2023/5/6 11:57
*/
public class ValidateCodeException extends AuthenticationException {
public ValidateCodeException(String s) {
super(s);
}
}
/**
* @author cmy
* @date 2023/5/6 12:24
*/
@Component
public class CaptchaAuthenticationFailureHandler implements AuthenticationFailureHandler {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
response.setContentType("application/json;charset=UTF-8");
response.setStatus(HttpStatus.BAD_REQUEST.value());
Map data = new HashMap<>();
data.put("data",null);
data.put("msg", exception.getMessage());
data.put("code",HttpStatus.BAD_REQUEST.value());
PrintWriter out = response.getWriter();
out.write(objectMapper.writeValueAsString(data));
}
}
configure方法中
captchaFilter.setFailureHandler(captchaAuthenticationFailureHandler);
.and().addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class);