在现代Web应用中,登录验证码功能是防止恶意登录、暴力破解密码等安全威胁的重要手段之一。通过引入验证码,可以有效防止自动化脚本的恶意攻击,提升系统的安全性。本文将详细介绍如何在Spring Boot项目中实现登录验证码功能。
验证码(CAPTCHA)是一种区分用户是计算机还是人的公共全自动程序。它可以有效防止恶意用户通过自动化脚本进行暴力破解、垃圾注册、恶意刷票等行为。常见的验证码类型包括数字验证码、字母验证码、图形验证码、滑动验证码等。
Spring Boot是一个基于Spring框架的快速开发框架,它简化了Spring应用的初始搭建和开发过程。通过自动配置和约定优于配置的原则,Spring Boot使得开发者能够快速构建独立运行的、生产级别的Spring应用。
首先,我们需要创建一个Spring Boot项目。可以通过Spring Initializr(https://start.spring.io/)快速生成一个Spring Boot项目。选择Maven或Gradle作为构建工具,并添加必要的依赖。
在pom.xml文件中添加以下依赖:
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Spring Boot Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Google Kaptcha -->
<dependency>
<groupId>com.github.axet</groupId>
<artifactId>kaptcha</artifactId>
<version>0.0.9</version>
</dependency>
</dependencies>
我们将使用Google的Kaptcha库来生成验证码。Kaptcha是一个简单易用的验证码生成库,支持多种验证码样式。
在application.properties文件中添加Kaptcha的配置:
# Kaptcha配置
kaptcha.border=yes
kaptcha.border.color=105,179,90
kaptcha.textproducer.font.color=blue
kaptcha.textproducer.font.size=45
kaptcha.textproducer.char.length=4
kaptcha.textproducer.char.space=2
kaptcha.image.width=200
kaptcha.image.height=50
接下来,我们需要创建一个验证码生成器。通过Kaptcha库,我们可以轻松生成验证码图片。
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
@Configuration
public class KaptchaConfig {
@Bean
public DefaultKaptcha getDefaultKaptcha() {
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
properties.setProperty("kaptcha.border", "yes");
properties.setProperty("kaptcha.border.color", "105,179,90");
properties.setProperty("kaptcha.textproducer.font.color", "blue");
properties.setProperty("kaptcha.textproducer.font.size", "45");
properties.setProperty("kaptcha.textproducer.char.length", "4");
properties.setProperty("kaptcha.textproducer.char.space", "2");
properties.setProperty("kaptcha.image.width", "200");
properties.setProperty("kaptcha.image.height", "50");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
生成验证码后,我们需要将其存储在服务器端,并在用户提交登录请求时进行验证。通常,我们可以将验证码存储在Session中。
import com.google.code.kaptcha.Producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;
@Controller
public class CaptchaController {
@Autowired
private Producer captchaProducer;
@GetMapping("/captcha")
public void getCaptcha(HttpServletRequest request, 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 = captchaProducer.createText();
HttpSession session = request.getSession();
session.setAttribute("captcha", capText);
BufferedImage bi = captchaProducer.createImage(capText);
ServletOutputStream out = response.getOutputStream();
ImageIO.write(bi, "jpg", out);
try {
out.flush();
} finally {
out.close();
}
}
}
在前端页面中,我们需要显示验证码图片,并允许用户输入验证码。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<h2>Login</h2>
<form th:action="@{/login}" method="post">
<div>
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
</div>
<div>
<label for="captcha">Captcha:</label>
<input type="text" id="captcha" name="captcha" required>
<img src="/captcha" onclick="this.src='/captcha?'+Math.random()" alt="Captcha">
</div>
<div>
<button type="submit">Login</button>
</div>
</form>
</body>
</html>
最后,我们需要改造登录接口,使其在验证用户名和密码之前,先验证用户输入的验证码是否正确。
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@Controller
public class LoginController {
@PostMapping("/login")
public String login(@RequestParam String username,
@RequestParam String password,
@RequestParam String captcha,
HttpServletRequest request) {
HttpSession session = request.getSession();
String sessionCaptcha = (String) session.getAttribute("captcha");
if (sessionCaptcha == null || !sessionCaptcha.equalsIgnoreCase(captcha)) {
return "redirect:/login?error=captcha";
}
// 验证用户名和密码
// ...
return "redirect:/home";
}
}
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
@Configuration
public class KaptchaConfig {
@Bean
public DefaultKaptcha getDefaultKaptcha() {
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
properties.setProperty("kaptcha.border", "yes");
properties.setProperty("kaptcha.border.color", "105,179,90");
properties.setProperty("kaptcha.textproducer.font.color", "blue");
properties.setProperty("kaptcha.textproducer.font.size", "45");
properties.setProperty("kaptcha.textproducer.char.length", "4");
properties.setProperty("kaptcha.textproducer.char.space", "2");
properties.setProperty("kaptcha.image.width", "200");
properties.setProperty("kaptcha.image.height", "50");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
import com.google.code.kaptcha.Producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;
@Controller
public class CaptchaController {
@Autowired
private Producer captchaProducer;
@GetMapping("/captcha")
public void getCaptcha(HttpServletRequest request, 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 = captchaProducer.createText();
HttpSession session = request.getSession();
session.setAttribute("captcha", capText);
BufferedImage bi = captchaProducer.createImage(capText);
ServletOutputStream out = response.getOutputStream();
ImageIO.write(bi, "jpg", out);
try {
out.flush();
} finally {
out.close();
}
}
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<h2>Login</h2>
<form th:action="@{/login}" method="post">
<div>
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
</div>
<div>
<label for="captcha">Captcha:</label>
<input type="text" id="captcha" name="captcha" required>
<img src="/captcha" onclick="this.src='/captcha?'+Math.random()" alt="Captcha">
</div>
<div>
<button type="submit">Login</button>
</div>
</form>
</body>
</html>
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@Controller
public class LoginController {
@PostMapping("/login")
public String login(@RequestParam String username,
@RequestParam String password,
@RequestParam String captcha,
HttpServletRequest request) {
HttpSession session = request.getSession();
String sessionCaptcha = (String) session.getAttribute("captcha");
if (sessionCaptcha == null || !sessionCaptcha.equalsIgnoreCase(captcha)) {
return "redirect:/login?error=captcha";
}
// 验证用户名和密码
// ...
return "redirect:/home";
}
}
在完成上述步骤后,我们可以启动Spring Boot应用,并访问登录页面。在输入用户名、密码和验证码后,系统会验证验证码是否正确。如果验证码错误,用户将被重定向回登录页面并显示错误信息。
/captcha接口能够正常访问。onclick事件刷新验证码图片,确保每次请求都能获取到新的验证码。通过本文的介绍,我们详细讲解了如何在Spring Boot项目中实现登录验证码功能。验证码的引入可以有效防止恶意登录和暴力破解,提升系统的安全性。希望本文能够帮助你在实际项目中顺利实现登录验证码功能。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。