# layui如何實現登錄界面驗證碼
## 一、驗證碼功能概述
驗證碼(CAPTCHA)是"Completely Automated Public Turing test to tell Computers and Humans Apart"的縮寫,用于區分人類用戶和自動化程序。在登錄界面中加入驗證碼可以有效防止暴力破解和惡意登錄攻擊。
### 1.1 驗證碼的主要作用
- 防止暴力破解:增加自動化嘗試的難度
- 提升安全性:阻擋大部分自動化攻擊腳本
- 區分人機:確保操作者是真實用戶
- 減輕服務器壓力:減少無效請求
### 1.2 layui實現驗證碼的優勢
- 輕量級框架,集成簡單
- 內置豐富的UI組件
- 良好的瀏覽器兼容性
- 簡潔的API設計
## 二、基礎環境準備
### 2.1 layui引入
```html
<!-- 引入layui核心文件 -->
<link rel="stylesheet" href="//unpkg.com/layui@2.6.8/dist/css/layui.css">
<script src="//unpkg.com/layui@2.6.8/dist/layui.js"></script>
<div class="layui-container">
<div class="layui-row">
<div class="layui-col-md4 layui-col-md-offset4">
<form class="layui-form" action="">
<div class="layui-form-item">
<label class="layui-form-label">用戶名</label>
<div class="layui-input-block">
<input type="text" name="username" required lay-verify="required" placeholder="請輸入用戶名" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">密碼</label>
<div class="layui-input-block">
<input type="password" name="password" required lay-verify="required" placeholder="請輸入密碼" autocomplete="off" class="layui-input">
</div>
</div>
<!-- 驗證碼區域 -->
<div class="layui-form-item">
<label class="layui-form-label">驗證碼</label>
<div class="layui-input-inline">
<input type="text" name="captcha" required lay-verify="required" placeholder="請輸入驗證碼" autocomplete="off" class="layui-input">
</div>
<div class="layui-form-mid layui-word-aux">
<img id="captchaImg" src="/captcha" onclick="refreshCaptcha()" style="cursor:pointer;">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="login">立即登錄</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
</div>
</div>
</div>
<!-- Maven依賴 -->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
@Configuration
public class KaptchaConfig {
@Bean
public Producer kaptchaProducer() {
Properties properties = new Properties();
properties.setProperty("kaptcha.image.width", "120");
properties.setProperty("kaptcha.image.height", "40");
properties.setProperty("kaptcha.textproducer.font.size", "30");
properties.setProperty("kaptcha.textproducer.char.length", "4");
properties.setProperty("kaptcha.textproducer.font.names", "宋體,楷體,微軟雅黑");
Config config = new Config(properties);
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
@RestController
@RequestMapping("/captcha")
public class CaptchaController {
@Autowired
private Producer kaptchaProducer;
@GetMapping
public void getCaptcha(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 禁止緩存
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 = kaptchaProducer.createText();
// 存入session
request.getSession().setAttribute("captcha", capText);
// 生成圖片
BufferedImage bi = kaptchaProducer.createImage(capText);
ServletOutputStream out = response.getOutputStream();
ImageIO.write(bi, "jpg", out);
try {
out.flush();
} finally {
out.close();
}
}
}
// 刷新驗證碼
function refreshCaptcha() {
document.getElementById('captchaImg').src = '/captcha?t=' + new Date().getTime();
}
layui.use(['form', 'layer'], function(){
var form = layui.form;
var layer = layui.layer;
// 表單提交
form.on('submit(login)', function(data){
// 驗證驗證碼
$.ajax({
url: '/verifyCaptcha',
type: 'POST',
data: {captcha: data.field.captcha},
success: function(res) {
if(res.success) {
// 驗證碼正確,提交登錄表單
$.post('/login', data.field, function(result) {
if(result.success) {
layer.msg('登錄成功', {icon: 1});
setTimeout(function(){
window.location.href = '/index';
}, 1000);
} else {
layer.msg(result.msg || '登錄失敗', {icon: 2});
refreshCaptcha();
}
});
} else {
layer.msg('驗證碼錯誤', {icon: 2});
refreshCaptcha();
}
}
});
return false;
});
});
@PostMapping("/verifyCaptcha")
public Map<String, Object> verifyCaptcha(@RequestParam String captcha, HttpSession session) {
Map<String, Object> result = new HashMap<>();
String sessionCaptcha = (String) session.getAttribute("captcha");
if (captcha == null || !captcha.equalsIgnoreCase(sessionCaptcha)) {
result.put("success", false);
result.put("msg", "驗證碼錯誤");
} else {
result.put("success", true);
// 驗證成功后移除session中的驗證碼
session.removeAttribute("captcha");
}
return result;
}
<script src="//unpkg.com/@alex_xu/slide-verify/dist/slide-verify.js"></script>
<link rel="stylesheet" href="//unpkg.com/@alex_xu/slide-verify/dist/slide-verify.css">
var slideVerify = new SlideVerify({
elementId: 'slider', // 容器ID
mode: 'fixed', // 模式:fixed固定模式,pop彈出模式
width: 350, // 寬度
height: 200, // 高度
sliderText: '向右滑動', // 提示文字
success: function() {
// 驗證成功回調
$('#hiddenCaptcha').val('verified');
}
});
// 發送短信驗證碼
function sendSmsCode() {
var phone = $('#phone').val();
if(!phone) {
layer.msg('請輸入手機號', {icon: 2});
return;
}
$.post('/sendSms', {phone: phone}, function(res) {
if(res.success) {
layer.msg('驗證碼已發送', {icon: 1});
startCountdown();
} else {
layer.msg(res.msg, {icon: 2});
}
});
}
// 倒計時功能
function startCountdown() {
var countdown = 60;
var $btn = $('#smsBtn');
$btn.attr('disabled', true);
var timer = setInterval(function() {
if(countdown <= 0) {
clearInterval(timer);
$btn.text('獲取驗證碼').attr('disabled', false);
} else {
$btn.text(countdown + '秒后重試');
countdown--;
}
}, 1000);
}
// 確保每次請求URL不同
function refreshCaptcha() {
var captchaImg = document.getElementById('captchaImg');
captchaImg.src = '/captcha?t=' + Date.now();
}
/* 響應式調整 */
@media screen and (max-width: 768px) {
.layui-form-item .layui-input-inline {
width: 100%;
}
#captchaImg {
width: 100%;
height: auto;
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>登錄驗證碼示例</title>
<link rel="stylesheet" href="//unpkg.com/layui@2.6.8/dist/css/layui.css">
<style>
.login-container {
margin-top: 100px;
}
.captcha-img {
height: 38px;
vertical-align: middle;
}
</style>
</head>
<body>
<div class="layui-container login-container">
<div class="layui-row">
<div class="layui-col-md4 layui-col-md-offset4">
<form class="layui-form" action="">
<div class="layui-form-item">
<label class="layui-form-label">用戶名</label>
<div class="layui-input-block">
<input type="text" name="username" required lay-verify="required" placeholder="請輸入用戶名" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">密碼</label>
<div class="layui-input-block">
<input type="password" name="password" required lay-verify="required" placeholder="請輸入密碼" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">驗證碼</label>
<div class="layui-input-inline">
<input type="text" name="captcha" required lay-verify="required" placeholder="請輸入驗證碼" autocomplete="off" class="layui-input">
</div>
<div class="layui-form-mid">
<img id="captchaImg" src="/captcha" onclick="refreshCaptcha()" class="captcha-img" title="點擊刷新">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="login">登錄</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
</div>
</div>
</div>
<script src="//unpkg.com/layui@2.6.8/dist/layui.js"></script>
<script src="//unpkg.com/jquery@3.6.0/dist/jquery.min.js"></script>
<script>
layui.use(['form', 'layer'], function(){
var form = layui.form;
var layer = layui.layer;
// 刷新驗證碼
window.refreshCaptcha = function() {
$('#captchaImg').attr('src', '/captcha?t=' + Date.now());
}
// 表單提交
form.on('submit(login)', function(data){
$.ajax({
url: '/verifyCaptcha',
type: 'POST',
data: {captcha: data.field.captcha},
success: function(res) {
if(res.success) {
// 驗證碼正確,提交登錄
$.post('/login', data.field, function(result) {
if(result.success) {
layer.msg('登錄成功', {icon: 1});
setTimeout(function(){
window.location.href = '/index';
}, 1000);
} else {
layer.msg(result.msg || '登錄失敗', {icon: 2});
refreshCaptcha();
}
});
} else {
layer.msg('驗證碼錯誤', {icon: 2});
refreshCaptcha();
}
}
});
return false;
});
});
</script>
</body>
</html>
本文詳細介紹了在layui框架中實現登錄驗證碼的完整方案,包括: 1. 基礎圖形驗證碼的實現 2. 前后端交互流程 3. 安全優化策略 4. 常見問題解決方案 5. 高級功能擴展思路
通過合理的驗證碼設計,可以顯著提升系統安全性,同時layui的簡潔API使得前端實現變得非常便捷。開發者可以根據實際需求選擇適合的驗證碼類型,并參考本文提供的優化建議構建更安全的登錄系統。 “`
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。