下面我来详细讲解“springboot登陆页面图片验证码简单的web项目实现”的完整攻略。
简介
本项目是一个基于Spring Boot框架的简单web项目,使用图片验证码来保护用户登录页面,防范恶意攻击和爆破。
实现步骤
第一步:新建Spring Boot项目
首先,我们需要新建一个Spring Boot项目,以便进行后续的开发。在创建项目时需要注意选择Web和Thymeleaf模板引擎。
第二步:添加验证码相关依赖
在pom.xml
文件中添加以下依赖:
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>3.10.2</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>1.0.0</version>
</dependency>
这里我们使用了阿里云提供的短信验证码服务。
第三步:编写验证码生成类
新建一个VerifyCodeUtils
类,用于生成随机验证码图片,并将验证码保存在Session中。
代码示例:
public class VerifyCodeUtils {
private static final String VERIFY_CODES = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
/**
* 生成随机验证码图片,并将验证码存储在session中
*
* @param width 图片宽度
* @param height 图片高度
* @param request HttpServletRequest对象
* @param response HttpServletResponse对象
* @param length 验证码长度
* @throws IOException
*/
public static void generateImage(int width, int height, HttpServletRequest request, HttpServletResponse response, int length) throws IOException {
String verifyCode = generateVerifyCode(length);
// 将验证码存储在Session中
HttpSession session = request.getSession();
session.setAttribute("verifyCode", verifyCode);
response.setContentType("image/jpeg");
//禁止图片缓存
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", -1);
OutputStream out = response.getOutputStream();
BufferedImage image = createImage(width, height, verifyCode);
ImageIO.write(image, "JPEG", out);
out.flush();
out.close();
}
/**
* 生成随机验证码
*
* @param length 验证码长度
* @return 验证码字符串
*/
public static String generateVerifyCode(int length) {
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
sb.append(VERIFY_CODES.charAt(new Random().nextInt(VERIFY_CODES.length())));
}
return sb.toString();
}
/**
* 创建验证码图片
*
* @param width 图片宽度
* @param height 图片高度
* @param verifyCode 验证码字符串
* @return BufferedImage对象
*/
public static BufferedImage createImage(int width, int height, String verifyCode) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
// 绘制背景
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, height);
// 绘制干扰线
Random r = new Random();
for (int i = 0; i < 10; i++) {
g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
int x1 = r.nextInt(width);
int y1 = r.nextInt(height);
int x2 = r.nextInt(width);
int y2 = r.nextInt(height);
g.drawLine(x1, y1, x2, y2);
}
// 绘制验证码
Font font = new Font("Arial", Font.BOLD, height - 4);
g.setFont(font);
for (int i = 0; i < verifyCode.length(); i++) {
char c = verifyCode.charAt(i);
g.setColor(new Color(r.nextInt(80), r.nextInt(80), r.nextInt(80)));
g.drawString(String.valueOf(c), (i + 1) * width / (verifyCode.length() + 1), height - 4);
}
return image;
}
}
第四步:编写发送短信验证码类
新建一个SmsUtils
类,用于发送短信验证码。
代码示例:
public class SmsUtils {
private static final String ACCESS_KEY_ID = "xxxx"; // 你自己的ACCESS_KEY_ID
private static final String ACCESS_KEY_SECRET = "xxxx"; // 你自己的ACCESS_KEY_SECRET
private static final String SIGN_NAME = "Aliyun短信测试专用"; // 在阿里云申请的短信签名
private static final String TEMPLATE_CODE = "SMS_0000001"; // 在阿里云申请的短信模板编号
/**
* 发送短信验证码
*
* @param phone 手机号码
* @param verifyCode 验证码
* @return 发送结果
* @throws ClientException
*/
public static SendSmsResponse sendSms(String phone, String verifyCode) throws ClientException {
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", ACCESS_KEY_ID, ACCESS_KEY_SECRET);
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", "Dysmsapi", "dysmsapi.aliyuncs.com");
IAcsClient client = new DefaultAcsClient(profile);
SendSmsRequest request = new SendSmsRequest();
request.setPhoneNumbers(phone); // 设置手机号码
request.setSignName(SIGN_NAME); // 设置短信签名
request.setTemplateCode(TEMPLATE_CODE); // 设置短信模板编号
request.setTemplateParam("{\"code\":\"" + verifyCode + "\"}"); // 设置模板参数:验证码
SendSmsResponse response = client.getAcsResponse(request);
return response;
}
}
第五步:添加验证码处理器
新建一个VerifyCodeController
类,用于处理验证码相关操作。
代码示例:
@Controller
public class VerifyCodeController {
@GetMapping("/verifyCode")
public void verifyCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
VerifyCodeUtils.generateImage(100, 40, request, response, 4);
}
@GetMapping("/sendVerifyCode")
@ResponseBody
public String sendVerifyCode(String phone, HttpServletRequest request) throws ClientException {
if (StringUtils.isEmpty(phone)) {
return "请输入手机号码";
}
// 生成6位数字验证码
String verifyCode = String.valueOf((int) ((Math.random() * 9 + 1) * 1_000_000));
// 发送验证码
SmsUtils.sendSms(phone, verifyCode);
// 将验证码存储在Session中
HttpSession session = request.getSession();
session.setAttribute("verifyCode", verifyCode);
return "success";
}
}
第六步:添加登陆相关代码
在LoginController
类中添加登陆相关代码。
代码示例:
@Controller
public class LoginController {
// 登录页面
@GetMapping("/")
public String login() {
return "login";
}
// 登录处理
@PostMapping("/doLogin")
public String doLogin(String username, String password, String verifyCode, HttpSession session) {
// 校验验证码
String code = (String) session.getAttribute("verifyCode");
if (StringUtils.isEmpty(code) || !code.equalsIgnoreCase(verifyCode)) {
// 验证码错误
return "redirect:/?error";
}
// 处理登录逻辑
if ("admin".equals(username) && "123456".equals(password)) {
return "redirect:/index";
} else {
return "redirect:/?error";
}
}
// 首页
@GetMapping("/index")
public String index() {
return "index";
}
// 欢迎页面
@GetMapping("/welcome")
public String welcome() {
return "welcome";
}
}
第七步:添加前端页面
最后,我们需要添加前端页面。以下是login.html
页面的代码:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Login</title>
<style>
.form-box {
margin: 50px auto;
width: 320px;
background: #fff;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
padding: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
text-align: center;
}
.form-box h1 {
font-size: 20px;
margin-bottom: 20px;
}
.form-box input {
width: 100%;
height: 40px;
padding: 0 20px;
margin-bottom: 20px;
box-sizing: border-box;
border: 1px solid #ccc;
border-radius: 5px;
outline: none;
}
.form-box .verify-code {
display: inline-block;
margin-bottom: 20px;
}
.form-box .verify-code img {
cursor: pointer;
margin-left: 10px;
vertical-align: middle;
}
.form-box button {
width: 100%;
height: 40px;
border: none;
border-radius: 5px;
color: #fff;
background: #4CAF50;
cursor: pointer;
outline: none;
}
.error {
color: red;
}
</style>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<div class="form-box">
<h1>Login</h1>
<form action="/doLogin" method="post">
<input type="text" name="username" placeholder="Username">
<input type="password" name="password" placeholder="Password">
<div class="verify-code">
<input type="text" name="verifyCode" placeholder="Verify Code">
<img src="/verifyCode" onclick="this.src='/verifyCode?'+Math.random()">
</div>
<button type="submit">Login</button>
</form>
<div th:if="${param.error}">
<p class="error">Invalid username or password</p>
</div>
</div>
<script type="text/javascript">
$(function () {
$('.verify-code img').click(function () {
this.src = '/verifyCode?' + Math.random();
});
$('button[type="submit"]').click(function (e) {
var phone = $('input[name="phone"]').val();
if (phone && !/^1\d{10}$/.test(phone)) {
alert('请输入正确的手机号码');
e.preventDefault();
}
var verifyCode = $('input[name="verifyCode"]').val();
if (verifyCode && verifyCode.length !== 4) {
alert('验证码长度必须为4位');
e.preventDefault();
}
});
$('button[name="sendVerifyCode"]').click(function () {
var phone = $('input[name="phone"]').val();
if (!phone) {
alert('请输入手机号码');
return;
}
if (!/^1\d{10}$/.test(phone)) {
alert('请输入正确的手机号码');
return;
}
$.get('/sendVerifyCode?phone=' + phone, function (data) {
if (data === 'success') {
var count = 60;
var timer = setInterval(function () {
count--;
if (count <= 0) {
clearInterval(timer);
$('button[name="sendVerifyCode"]').prop('disabled', false).text('发送验证码');
return;
}
$('button[name="sendVerifyCode"]').prop('disabled', true).text(count + '秒后重发');
}, 1000);
} else {
alert(data);
}
});
});
});
</script>
</body>
</html>
至此,整个项目的实现就完成了。我们可以启动该项目并访问http://localhost:8080
来体验验证码功能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:springboot登陆页面图片验证码简单的web项目实现 - Python技术站