图形验证码
自定义过滤器
相关代码如下
- 获取图片验证码
@Controller
public class CaptchaController {
@Autowired
private Producer producer;
@Autowired
private HttpServletRequest request;
@Autowired
private HttpServletResponse response;
/**
* 生成图片验证码
* @throws IOException
*/
@GetMapping("/getCaptcha.jpg")
public void getCaptcha() throws IOException {
//生成文本内容
String capText=producer.createText();
request.getSession().removeAttribute("captcha");
//将图片输出给浏览器
response.setContentType("image/jpeg");
//保存到session里面
request.getSession().setAttribute("captcha",capText);
//生成图片
BufferedImage image = producer.createImage(capText);
try(ServletOutputStream outputStream = response.getOutputStream()) {
ImageIO.write(image,"jpeg",outputStream);
}catch (Exception e){
throw e;
}
}
}
- kaptcha 配置
@Configuration
public class CaptchaConfig {
@Bean
public Producer producer(){
//kaptcha 配置
Properties properties = new Properties();
//图片宽度
properties.setProperty("kaptcha.image.width","100");
//图片长度
properties.setProperty("kaptcha.image.height","40");
//字符集
properties.setProperty("kaptcha.textproducer.char.string","abc0123456789");
//字符长度
properties.setProperty("kaptcha.textproducer.char.length","4");
//使用默认的图形验证码
DefaultKaptcha kaptcha = new DefaultKaptcha();
Config config=new Config(properties);
kaptcha.setConfig(config);
return kaptcha;
}
}
- Security配置
@EnableWebSecurity
@Configuration
public class SecurityCaptchaConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/getCaptcha.jpg")
.permitAll().anyRequest().authenticated().and()
.formLogin().loginPage("/myLogin.html").
loginProcessingUrl("/login").failureHandler(myAuthenticationFailureHandler()).permitAll().and().
addFilterBefore(verificationCodeFilter(), UsernamePasswordAuthenticationFilter.class).
csrf().disable();
}
@Bean
public VerificationCodeFilter verificationCodeFilter(){
return new VerificationCodeFilter();
}
@Bean
public MyAuthenticationFailureHandler myAuthenticationFailureHandler() {
return new MyAuthenticationFailureHandler();
}
}
- 校验验证码过滤器
public class VerificationCodeFilter extends OncePerRequestFilter {
@Autowired
private AuthenticationFailureHandler authenticationFailureHandler ;
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
//非登陆请求不校验验证码
if("/login".equals(httpServletRequest.getRequestURI())){
try {
verifyCode(httpServletRequest);
filterChain.doFilter(httpServletRequest,httpServletResponse);
}catch (VerificationCodeException e){
authenticationFailureHandler.onAuthenticationFailure(httpServletRequest,httpServletResponse,e);
}
}else{
filterChain.doFilter(httpServletRequest,httpServletResponse);
}
}
public void verifyCode(HttpServletRequest request) throws VerificationCodeException{
String requestCode= request.getParameter("captcha");
HttpSession session = request.getSession();
String sessionCode = (String)session.getAttribute("captcha");
System.out.println("sessionCode:"+sessionCode+"requestCode:"+requestCode);
if(!StringUtils.isEmpty(sessionCode)){
//每次调用登陆请求都刷新验证码
session.removeAttribute("captcha");
}
//校验不通过抛出异常
if(StringUtils.isEmpty((requestCode))||StringUtils.isEmpty(sessionCode)||!requestCode.equals(sessionCode)){
throw new VerificationCodeException();
}
}
}
- 自定义验证码异常类
public class VerificationCodeException extends AuthenticationException {
public VerificationCodeException(){
super("图形验证码校验失败");
}
}
- 异常处理
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
response.setContentType("application/json;charset=UTF-8");
PrintWriter out=response.getWriter();
Map<String,String> resultMap = new HashMap<>();
resultMap.put("code","1001");
if(e instanceof VerificationCodeException){
resultMap.put("code","1002");
resultMap.put("msg",e.getMessage());
}
resultMap.put("msg",e.getMessage());
out.write(JSON.toJSONString(resultMap));
}
}
- Html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<form action="login" method="post">
<table>
<tr>
<td>用户名:<input type="text" name="username"/></td>
</tr>
<tr>
<td>密码:<input type="password" name="password"/></td>
</tr>
<tr>
<td> <input type="text" name="captcha" placeholder="captcha" />
<img src="/getCaptcha.jpg" alt="captcha" style="margin-left: 20px;"></td>
</tr>
<tr>
<td colspan="2">
<button type="submit">登录</button>
</td>
</tr>
</table>
</form>
</div>
</body>
</html>
<style>
div{
width: 400px;
height: 400px;
margin: 0 auto;
}
</style>
- 前端界面
当我们输入错误的验证码时: