1、导入依赖jar包,该jar包提供了一个图形验证码工具类CaptchaUtil
<!--引入hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.9</version>
</dependency>
2、编写获取验证码的Controller
/*
* 获取验证码的Controller
*/
@Controller
@RequestMapping("code")
public class CodeValidate {
/**
* 访问该路径生成验证码
* @param req
* @param resp
*/
@GetMapping("image")
public void code(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 创建一个验证码 长,宽,字符数,干扰元素个数
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100, 4, 10);
// 将验证码放到session中以供前端获取展示
String code = lineCaptcha.getCode();//真实验证码
req.getSession().setAttribute("code",code);
// 用流写出去
lineCaptcha.write(resp.getOutputStream());
}
}
3、设置验证码过滤器实现Filter接口,进行登陆前的验证
/*
* 检查验证码的合法性
*/
@Component
public class CodeValidateFiler implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req =(HttpServletRequest)servletRequest;
HttpServletResponse resp =(HttpServletResponse)servletResponse;
//获取当前请求的Url
String requestURI = req.getRequestURI();
//判断 如果是登录的请求,需要验证code,不是登录 就放行
if(requestURI.equals("/login/dologin")){
// 获取存放到session中的验证码
String codeVali = req.getSession().getAttribute("code").toString();
// 获取传过来的验证码
String code = req.getParameter("code");
//判断传过来的验证码是否存在
if(StringUtils.hasText(code)){
// 将传过来的验证码与生成的验证码进行比较
if(code.equals(codeVali)){
// 相等放行
filterChain.doFilter(req,resp);
}else{
// 不相等重新登录
req.setAttribute("error","验证码不正确");
resp.sendRedirect("/login/tologin");
}
}else{
// 验证码为空重定向到登录页
req.getSession().setAttribute("error","验证码不能为空");
resp.sendRedirect("/login/tologin");
}
}else{
// 其他路径放行
filterChain.doFilter(req,resp);
}
}
}
4、注册进HttpSecurity中
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启方法级别的权限认证 默认是false
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling().accessDeniedHandler(appAuthDenyHander);
//在登录验证之前,先判断验证是否正确,因此验证码过滤器要在身份验证过滤器之前进行过滤
http.addFilterBefore(codeValidateFiler, UsernamePasswordAuthenticationFilter.class);
http.formLogin().successHandler(appAuthSuccessHandler).failureHandler(appAuthFailHandler)
.usernameParameter("username")
.passwordParameter("password")//自定义表单用户名和密码的参数名
.loginPage("/login/toLogin")//自定义的,登录页面
.loginProcessingUrl("/login/doLogin")//真正登录接口
.successForwardUrl("/login/main") //登录成功跳转的url
.failureForwardUrl("/login/toLogin") //登录失败跳转登录页
.permitAll();//全部放行
//自定义退出
http.logout()
.logoutUrl("/lout")//自定义的退出路径
.logoutSuccessUrl("/login/toLogin") //退出成功后的跳转路径
.permitAll();
}
}
5、编写登陆页
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login/doLogin" method="post">
<div>
用户名: <input type="text" name="username">
</div>
<div>
密碼: <input type="text" name="password">
</div>
<div>
验证码: <input type="text" name="code">
<img src="/code/image" alt="">
<span style="color: red" th:text="${session.error}"></span>
</div>
<div>
<input type="submit" value="登录">
</div>
</form>
</body>
</html>
5、测试