如何在Golang中实现Web表单验证码
在Web开发中,验证码是一种常见的安全措施,用于防止自动化程序恶意提交表单。本文将介绍如何在Golang中实现Web表单验证码功能。
实现思路
我们将使用以下技术栈来实现验证码功能:
Golang作为后端语言
net/http包处理HTTP请求
第三方库github.com/mojocn/base64Captcha创建验证码图片
HTML/CSS/JavaScript构建前端页面
步骤一:安装依赖
首先,我们需要安装base64Captcha库:
go get github.com/mojocn/base64Captcha
步骤二:创建验证码服务
接下来,我们创建一个验证码服务,用于生成验证码图片和验证用户输入:
package main
import (
"encoding/json"
"fmt"
"github.com/mojocn/base64Captcha"
"log"
"net/http"
)
// ConfigJsonBody 定义验证码配置结构体
type ConfigJsonBody struct {
Id string
CaptchaType string
VerifyValue string
DriverAudio *base64Captcha.DriverAudio
DriverString *base64Captcha.DriverString
DriverChinese *base64Captcha.DriverChinese
DriverMath *base64Captcha.DriverMath
DriverDigit *base64Captcha.DriverDigit
}
var store = base64Captcha.DefaultMemStore
func main() {
// 设置路由
http.HandleFunc("/captcha", generateCaptcha)
http.HandleFunc("/verify", verifyCaptcha)
http.HandleFunc("/", indexHandler)
// 启动服务器
fmt.Println("Server starting on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
// indexHandler 处理首页请求
func indexHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
// 返回包含验证码表单的HTML页面
html := `
<!DOCTYPE html>
<html>
<head>
<title>验证码示例</title>
<style>
body { font-family: Arial, sans-serif; margin: 50px; }
.form-group { margin-bottom: 15px; }
label { display: inline-block; width: 100px; }
input[type="text"] { padding: 8px; width: 200px; }
button { padding: 10px 20px; background-color: #007bff; color: white; border: none; cursor: pointer; }
button:hover { background-color: #0056b3; }
#captchaImage { vertical-align: middle; margin-left: 10px; }
</style>
</head>
<body>
<h1>验证码示例</h1>
<form id="captchaForm">
<div class="form-group">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required>
</div>
<div class="form-group">
<label for="password">密码:</label>
<input type="text" id="password" name="password" required>
</div>
<div class="form-group">
<label for="captcha">验证码:</label>
<input type="text" id="captcha" name="captcha" required>
<img id="captchaImage" src="/captcha" onclick="refreshCaptcha()" style="cursor:pointer;" title="点击刷新">
</div>
<button type="submit">提交</button>
</form>
<script>
function refreshCaptcha() {
var captchaImage = document.getElementById('captchaImage');
captchaImage.src = '/captcha?' + new Date().getTime(); // 添加时间戳避免缓存
}
document.getElementById('captchaForm').addEventListener('submit', function(e) {
e.preventDefault();
var formData = new FormData(this);
fetch('/verify', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('验证成功!');
// 这里可以提交表单或进行其他操作
} else {
alert('验证失败:' + data.message);
refreshCaptcha(); // 刷新验证码
}
})
.catch(error => {
console.error('Error:', error);
alert('请求失败,请重试');
});
});
</script>
</body>
</html>`
w.Header().Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprint(w, html)
} else {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
}
// generateCaptcha 生成验证码
func generateCaptcha(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// 配置验证码参数
driver := &base64Captcha.DriverString{
Height: 80,
Width: 240,
NoiseCount: 0,
ShowLineOptions: 2,
Length: 4,
Source: "abcdefghjkmnpqrstuvwxyz23456789",
Fonts: []string{"chromohv.ttf"},
BgColor: &color.RGBA{R: 3, G: 102, B: 214, A: 3},
FontsScale: 1.2,
}
captcha := base64Captcha.NewCaptcha(driver, store)
id, b64s, err := captcha.Generate()
if err != nil {
http.Error(w, "生成验证码失败", http.StatusInternalServerError)
return
}
// 返回JSON格式的验证码数据
response := map[string]string{
"captchaId": id,
"captchaImage": b64s,
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
json.NewEncoder(w).Encode(response)
}
// verifyCaptcha 验证验证码
func verifyCaptcha(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// 获取表单数据
err := r.ParseForm()
if err != nil {
http.Error(w, "解析表单失败", http.StatusBadRequest)
return
}
captchaId := r.FormValue("captchaId")
captchaCode := r.FormValue("captcha")
// 验证验证码
if store.Verify(captchaId, captchaCode, true) {
// 验证成功
response := map[string]interface{}{
"success": true,
"message": "验证成功",
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
json.NewEncoder(w).Encode(response)
} else {
// 验证失败
response := map[string]interface{}{
"success": false,
"message": "验证码错误或已过期",
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
json.NewEncoder(w).Encode(response)
}
}代码说明
1. 依赖安装
我们使用go get命令安装base64Captcha库,这是一个用于生成验证码的Go语言库。
2. 验证码服务
main函数中设置了三个路由:
/:返回包含验证码表单的HTML页面
/captcha:生成验证码图片并返回给客户端
/verify:验证用户输入的验证码是否正确
3. 验证码生成
generateCaptcha函数配置了验证码的参数,包括高度、宽度、噪声数量、线条选项、长度、字符源和字体等。然后使用base64Captcha.NewCaptcha创建验证码,并生成验证码ID和Base64编码的图片数据。
4. 验证码验证
verifyCaptcha函数从表单中获取验证码ID和用户提交的验证码,然后调用store.Verify方法进行验证。如果验证成功,返回成功的JSON响应;否则返回失败的JSON响应。
5. 前端页面
indexHandler函数返回的HTML页面包含一个简单的登录表单,其中有用户名、密码和验证码输入框。验证码图片可以通过点击刷新,表单提交时会通过JavaScript发送异步请求到/verify接口进行验证。
运行程序
保存上述代码到一个名为main.go的文件中,然后在终端中运行以下命令:
go run main.go
然后在浏览器中访问http://localhost:8080,即可看到验证码表单。
总结
本文介绍了如何使用Golang和base64Captcha库实现Web表单验证码功能。通过生成验证码图片并在前端展示,用户输入验证码后发送到后端进行验证,可以有效防止自动化程序的恶意提交。你可以根据实际需求调整验证码的参数和样式,以满足不同的安全需求。