Springboot3.x 中實現滑動拼圖驗證碼的全面指南
滑動拼圖驗證碼作為用戶身份驗證的一種方式,它的主要作用是進行人機行為區分,防止針對網站或者應用的惡意機器行為。這種驗證碼尤其適用于防止惡意的批量注冊、登錄爬蟲以及自動化攻擊,比如說防止一些驗證碼識別的機器人。
基本的滑動拼圖驗證碼通常由一個背景圖像和一個缺失的圖像片段組成,用戶需要通過鼠標操作將缺失的片段準確滑動至應在的位置。在這個過程中,用戶的行為數據(包括滑動軌跡,滑動速度,滑動時間等)都可以被用來進行用戶和機器的區分,因此滑動拼圖驗證碼又有著非常高的安全性。
與傳統的文本驗證碼相比,滑動拼圖驗證碼具有更好的用戶體驗和更高的安全性:文本驗證碼往往需要用戶仔細觀察,輸入錯誤率高,給用戶帶來不便,而且現在有許多OCR技術可以成功識別文本驗證碼。滑動拼圖驗證碼則只需要用戶執行一個自然的,直覺的動作,用戶錯誤率低,同時機器人模擬出人類完全一致的行為幾乎是不可能的。
理解原理:滑動拼圖驗證碼的運行機制
滑動拼圖驗證碼的運行包括了后端服務和前端交互兩大部分,我們先來知道整體的流程,再逐一深入。
- 后端生成圖像:后端首先生成一張完整的圖像和一個帶有缺口的復制圖像。這個缺口通常是一個特定的形狀,如圓形、方形等,或者是一段特定輪廓的形狀。這樣就形成了一對背景圖像和滑塊圖像,缺口的形狀和大小在這兩張圖像中是完全一致的。
- 前端展示與交互:后端將這兩張圖像發送給前端,前端將背景圖像正常展示,而滑塊圖像則位于一邊,等待用戶進行拖動。
- 用戶操作滑塊:用戶通過鼠標或觸屏操作,將滑塊圖像拖動至背景圖像中的缺口部分。在這個操作過程中,前端會記錄下用戶的行為數據,這些數據包括但不限于滑動開始和結束的時間、滑動軌跡、滑動速度等。
- 前端發送驗證數據:當用戶完成拖動后,或者用戶拖動滑塊超出一定范圍后,前端將滑動的結果以及行為數據發送給后端。這個結果就是滑塊在背景圖像中的位置,或者說是滑動的距離。
- 后端驗證:后端根據發送來的滑動結果,以及用戶的行為數據,進行驗證。如果滑動結果與后端最初設定的缺口位置一致,或者在一定的誤差范圍內,同時用戶的行為數據也符合正常人類的行為,那么后端判定這次驗證碼驗證成功,返回驗證成功的結果。
技術實現:在Springboot3.x中如何生成滑動拼圖驗證碼
下面我們將實現一個簡單的 Spring Boot 工程來生成滑動拼圖驗證碼。我們的項目中主要包括四個部分,分別為原始圖片的獲取,將原始圖片轉換為帶缺口的滑動驗證碼圖片,前端的驗證碼顯示和操作以及后端的數據驗證。
后端:生成滑動拼圖驗證碼
我們首先需要一個原始圖片,這個圖片將會被轉換為驗證碼圖片。原始圖片可以是任何圖片文件,例如originalImage.png,存放在項目的資源文件夾中。
后端用來生成驗證碼的核心代碼如下:
@RestController
public class ImageController {
private final ImageService imageService;
public ImageController(ImageService imageService) {
this.imageService = imageService;
}
@GetMapping("/captcha")
public ResponseEntity<byte[]> getCaptcha(HttpSession session) throws IOException {
BufferedImage captchaImage = imageService.createCaptchaImage();
session.setAttribute("captcha", imageService.getCaptchaPosition());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(captchaImage, "png", baos);
byte[] imageInByte = baos.toByteArray();
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_TYPE, MediaType.IMAGE_PNG_VALUE)
.body(imageInByte);
}
@PostMapping("/validate")
public boolean validateCaptcha(@RequestParam int position, HttpSession session) {
Integer captchaPosition = (Integer) session.getAttribute("captcha");
if (captchaPosition != null) {
return Math.abs(captchaPosition - position) <= 5;
}
return false;
}
}
在這段代碼中,/captcha路由用來生成驗證碼圖片并返回給前端,生成的驗證碼圖片是一個PNG格式的圖片。同時,將驗證碼圖片中缺口的位置保存在session中,用來進行后續的驗證。/validate路由用來驗證用戶的操作是否正確。
ImageService 類
import org.springframework.stereotype.Service;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Paths;
import javax.imageio.ImageIO;
import java.util.Random;
@Service
public class ImageService {
private int captchaPosition;
public BufferedImage createCaptchaImage() throws IOException {
BufferedImage originalImage = readImageFromResources();
captchaPosition = generateRandomCaptchaPosition(originalImage.getWidth());
BufferedImage captchaImage = new BufferedImage(
originalImage.getWidth(),
originalImage.getHeight(),
originalImage.getType());
int pieceWidth = originalImage.getWidth() / 8;
// 繪制原始圖像
Graphics2D graphics2D = captchaImage.createGraphics();
graphics2D.drawImage(originalImage, 0, 0, null);
// 在原始位置繪制一個帶形狀的片段
graphics2D.setComposite(AlphaComposite.Clear);
graphics2D.fillRoundRect(captchaPosition, captchaImage.getHeight() / 2, pieceWidth, pieceWidth, 10, 10);
graphics2D.dispose();
return captchaImage;
}
private BufferedImage readImageFromResources() throws IOException {
InputStream inputStream = getClass().getResourceAsStream(Paths.get("path_to_resources", "originalImage.png").toString());
return ImageIO.read(inputStream);
}
private static int generateRandomCaptchaPosition(int width) {
Random random = new Random();
return random.nextInt(width / 2) + width / 4; // 將片段定位到圖像的中央位置
}
public int getCaptchaPosition() {
return captchaPosition;
}
}
這個 ImageService 類實現了 createCaptchaImage 方法,這個方法可以生成一個滑動拼圖驗證碼。首先,它讀取了一個原始的圖像文件,然后隨機生成了一個驗證碼的位置。接著,它創建了一個新的 BufferedImage 對象,將原始圖像繪制到了這個新的對象上,然后在驗證碼位置上繪制了一個透明的缺口。
前端:驗證碼的顯示和操作
前端使用HTML和JavaScript來顯示驗證碼圖片和處理用戶的操作。核心代碼如下:
<img id="captcha" src="api/captcha" />
<div id="slider"><div id="knob"></div></div>
<script>
const slider = document.getElementById('slider');
const knob = document.getElementById('knob');
knob.onmousedown = function(event) {
event.preventDefault();
let shiftX = event.clientX - knob.getBoundingClientRect().left;
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
function onMouseMove(event) {
let newLeft = event.clientX - shiftX - slider.getBoundingClientRect().left;
if (newLeft < 0) newLeft = 0;
let rightEdge = slider.offsetWidth - knob.offsetWidth;
if (newLeft > rightEdge) newLeft = rightEdge;
knob.style.left = newLeft + 'px';
}
function onMouseUp() {
document.removeEventListener('mouseup', onMouseUp);
document.removeEventListener('mousemove', onMouseMove);
validateCaptcha(parseInt(knob.style.left));
}
};
knob.ondragstart = function() { return false; }
function validateCaptcha(position) {
fetch('api/validate?position=' + position, {method: 'POST'})
.then(response => response.json())
.then(data => { /* process the validation result */ });
}
</script>
在這段代碼中,顯示驗證碼的元素從后端請求驗證碼圖片。滑動條(<div id="slider">)和滑塊(<div id="knob">)用來讓用戶進行操作。當用戶按下滑塊時,開始記錄滑塊的位置,當用戶釋放滑塊時,將滑塊的位置發送給后端進行驗證。
實戰應用:滑動拼圖驗證碼的應用示例
滑動拼圖驗證碼是一種常見的人機驗證工具,主要用于區別用戶是人還是機器人。其操作方式通常是,用戶通過拖動滑塊,將一個圖形拼圖從初始位置移動到一個預定的位置,如此一來,系統就可以通過這種操作行為來判斷用戶是否為人類。下面是一個具體的應用示例:
假如你正在構建一個網站,希望在用戶注冊或登錄時,通過滑動拼圖驗證碼來增強系統的安全防護。在用戶填寫完用戶名和密碼后,必須要求他們通過滑動拼圖驗證碼的驗證,才能進一步操作。
- 用戶首先訪問你的網站,并點擊注冊或登錄按鈕。
- 用戶在相應的輸入框內填入用戶名和密碼。
- 此時,網站會顯示出一個滑動拼圖驗證碼,同時,網站也會提示用戶需要通過拖動滑塊,將拼圖移動到正確的位置。
- 用戶根據提示操作,移動滑塊,將拼圖還原到指定位置。
- 用戶成功完成滑動拼圖驗證碼后,就可以繼續注冊或登錄操作。
引入滑動拼圖驗證碼,可以有效增強你的網站對惡意機器人的防護能力,從而提高用戶數據的安全性。同時,這種方式也很友好,用戶體驗良好,是一種十分實用的人機交互方式。
本文詳細而深入地介紹了滑動拼圖驗證碼的工作原理及其在實戰中的應用。文章首先解釋了什么是滑動拼圖驗證碼,它如何幫助識別用戶是否為人類,提高系統的安全性。然后,文章通過一個具體的實例,詳細地描述了如何在用戶注冊和登錄的過程中,使用滑動拼圖驗證碼增強網站的安全防護能力。總結而言,滑動拼圖驗證碼是一種有效且用戶體驗良好的防護機制,能夠針對惡意機器人采取防護措施,提高用戶數據的安全性。