导入项目依赖
<!--hutool工具包-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.6.8</version>
</dependency>
Controller层新建getCaptcha()方法
/*
* 利用hutool工具包生成登录验证码
*/
@GetMapping(value = "/login/getCaptcha")
public void getCaptcha(HttpServletResponse response, HttpSession session) throws IOException {
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(116,36,4,10);
session.setAttribute("captcha",lineCaptcha.getCode());
try{
ServletOutputStream outputStream = response.getOutputStream();
lineCaptcha.write(outputStream);
outputStream.close();
}catch (IOException e){
e.printStackTrace();
}
}
登录页面
<!DOCTYPE html>
<html lang="en">
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登录页</title>
<link rel="stylesheet" type="text/css" href="/css/layui.css"/>
</head>
<body>
<div>
<form th:action="@{/login}" method="post" class="layui-form">
<div class="layui-form-item">
<label class="layui-form-label">用户名:</label>
<div class="layui-input-inline">
<input placeholder="请输入用户名" name="username" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">密码:</label>
<div class="layui-input-inline">
<input placeholder="请输入密码" name="password" required lay-verify="required" class="layui-input" type="password">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">验证码:</label>
<div class="layui-input-inline">
<input type="text" placeholder="请输入验证码" name="captcha" required autocomplete="off" class="layui-input">
</div>
<div class="layui-input-inline">
<img th:src="@{/login/getCaptcha}" onclick="this.src=this.src+'?'">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" type="submit">登录</button>
</div>
</div>
</form>
</div>
</body>
<script type="text/javascript" src="/js/layui.js"></script>
<script type="text/javascript" sec="jquery-3.5.1.min.js"></script>
</html>
SecurityConfig对/login/getCaptcha方法放行
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
//主页、注册页放行
.antMatchers("/","/index","/register","/login/**")
.permitAll()
//静态资源文件放行
.antMatchers("/css/**","/js/**","/img/**")
.permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll()
.and().csrf().disable();
// session管理
http.sessionManagement().invalidSessionUrl("/login")
.maximumSessions(1);
}
新建CaptchaVerifyException验证码验证异常类
import org.springframework.security.core.AuthenticationException;
public class CaptchaVerifyException extends AuthenticationException {
public CaptchaVerifyException(String msg) {
super(msg);
}
}
新建CaptchaVerifyFilter验证码验证过滤器
public class CaptchaVerifyFilter extends OncePerRequestFilter {
private AuthenticationFailureHandler failureHandler;
public CaptchaVerifyFilter(AuthenticationFailureHandler failureHandler) {
this.failureHandler = failureHandler;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
//只对 /login 的post请求过滤, /login 的get请求为返回登录页面
if(request.getMethod().equals("post") && request.getRequestURI().equals("/login")){
String captcha = request.getParameter("captcha");
HttpSession session = request.getSession();
String expect = (String) session.getAttribute("captcha");
if(!expect.isEmpty()){
session.removeAttribute("captcha");
}
if(!expect.equals(captcha)){
try{
throw new CaptchaVerifyException("验证码错误!");
}catch (CaptchaVerifyException e){
failureHandler.onAuthenticationFailure(request,response,e);
}
}else {
filterChain.doFilter(request,response);
}
}else {
filterChain.doFilter(request,response);
}
}
}
将CaptchaVerifyFilter过滤器添加到Security配置类,并添加到UsernamePasswordAuthenticationFiler前
@Override
protected void configure(HttpSecurity http) throws Exception {
// session管理
http.sessionManagement().invalidSessionUrl("/login")
.maximumSessions(1);
http.addFilterBefore(new CaptchaVerifyFilter(authenticationFailureHandler()), UsernamePasswordAuthenticationFilter.class);
}
登录页面
登录成功跳转主页面