go生成验证码

go生成验证码

一.两种验证码实现方法

Go 里比较常见的验证码实现方式主要有两种:


方案一:使用 github.com/dchest/captcha

步骤

  1. 引入依赖

    1
    go get github.com/dchest/captcha
  2. 生成验证码

    • 调用 captcha.NewLen(6) 生成验证码 ID(6 位长度)。
    • 通过 captcha.WriteImage(w, id, width, height) 输出 PNG 图片。
  3. 校验验证码

    • 使用 captcha.VerifyString(id, userInput) 进行验证。
  4. 前端展示

    • 前端 <img src="/captcha/image?id=xxx"> 显示验证码图片。
    • 提交时携带 id + code 调用 /captcha/verify 接口验证。

思路

  • dchest/captcha 直接在后端生成 PNG 图片,前端 <img> 标签展示。
  • 适合传统 Web 项目,结构清晰。
  • 优点:简单、稳定、广泛使用。
  • 缺点:只能输出图片,不方便前端组件化或跨端(比如 App)。

方案二:使用 github.com/mojocn/base64Captcha

步骤

  1. 引入依赖

    1
    go get github.com/mojocn/base64Captcha
  2. 定义验证码驱动

    • 可以选择不同类型:数字、字母、算术题、中文等。

    • 例如:

      1
      driver := base64Captcha.NewDriverDigit(80, 240, 6, 0.7, 80)
  3. 生成验证码

    • 使用 NewCaptcha(driver, store) 创建对象。
    • 调用 Generate() 获取 (id, base64Image, answer, err)
  4. 校验验证码

    • 使用 store.Verify(id, userInput, clear) 验证输入是否正确。
  5. 前端展示

    • 后端返回 JSON,包含 idbase64 图片字符串
    • 前端 <img src="data:image/png;base64,..."> 直接展示。

思路

  • base64Captcha 返回的是 Base64 字符串,无需额外图片接口,前端能直接展示。
  • 适合前后端分离、移动端、小程序。
  • 优点:支持多种验证码类型(算术、中文、音频)、更灵活。
  • 缺点:比 dchest/captcha 稍复杂,内存存储不适合分布式(要改成 Redis 存储)。

🔹 对比总结

特点 dchest/captcha base64Captcha
输出形式 PNG 图片(URL 访问) Base64 图片字符串(直接 JSON 返回)
支持类型 数字/字母图片 数字、字母、算术题、中文、音频等
前端展示 <img src="/captcha/image?id=xxx"> <img src="data:image/png;base64,...">
校验方式 captcha.VerifyString(id, code) store.Verify(id, code, clear)
存储 内存(可扩展) 默认内存(可改 Redis)
场景 传统 Web 表单 前后端分离、App、小程序

👉 总结一句话:

  • **dchest/captcha**:简单直接,生成图片验证码,适合传统 Web 项目。
  • **base64Captcha**:功能更强,返回 Base64,适合前后端分离和跨端应用。

流程图(从生成 → 前端展示 → 验证)对比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
            ┌─────────────────────────┐
│ 后端 (Go) │
└─────────────┬───────────┘

生成验证码 (ID + 图片/字符串)

┌─────────────────┼──────────────────┐
│ │
┌───────▼─────────┐ ┌────────▼─────────┐
│ dchest/captcha │ │ base64Captcha │
└───────┬─────────┘ └────────┬─────────┘
│ │
1. captcha.NewLen(6) 1. 定义 Driver (数字/算术/中文)
2. captcha.WriteImage(w,id,...) 2. c := NewCaptcha(driver,store)
3. 生成 PNG 图片 URL 3. c.Generate() → (id, base64Str)
│ │
│ │
▼ ▼
┌───────────────────┐ ┌────────────────────┐
│ 前端获取 URL │ │ 前端获取 JSON │
│ <img src="/captcha│ │ {id, base64Image} │
│ /image?id=xxx" />│ │ <img src="data:..."/> │
└─────────┬─────────┘ └─────────┬──────────┘
│ │
用户输入验证码字符串 用户输入验证码字符串
│ │
┌─────────▼─────────┐ ┌─────────▼──────────┐
│ 后端验证 │ │ 后端验证 │
│ VerifyString(id, │ │ store.Verify(id, │
│ userInput) │ │ userInput, true) │
└─────────┬─────────┘ └─────────┬──────────┘
│ │
▼ ▼
返回 true/false (验证结果) 返回 true/false (验证结果)

二.go生成验证码实现案例


🚀 Demo 1:使用 dchest/captcha

后端代码 (main.go)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package main

import (
"encoding/json"
"log"
"net/http"

"github.com/dchest/captcha"
)

// 生成验证码 ID
func generateHandler(w http.ResponseWriter, r *http.Request) {
id := captcha.NewLen(6) // 6 位数字
resp := map[string]string{"id": id}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(resp)
}

// 输出验证码图片
func imageHandler(w http.ResponseWriter, r *http.Request) {
id := r.URL.Query().Get("id")
if id == "" {
http.Error(w, "missing id", http.StatusBadRequest)
return
}
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
captcha.WriteImage(w, id, 240, 80) // 宽240,高80
}

// 验证验证码
func verifyHandler(w http.ResponseWriter, r *http.Request) {
type req struct {
ID string `json:"id"`
Code string `json:"code"`
}
var in req
if err := json.NewDecoder(r.Body).Decode(&in); err != nil {
http.Error(w, "invalid body", http.StatusBadRequest)
return
}
ok := captcha.VerifyString(in.ID, in.Code)
resp := map[string]bool{"ok": ok}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(resp)
}

func main() {
http.HandleFunc("/captcha/generate", generateHandler)
http.HandleFunc("/captcha/image", imageHandler)
http.HandleFunc("/captcha/verify", verifyHandler)
http.Handle("/", http.FileServer(http.Dir("."))) // 提供 index.html

log.Println("http://localhost:8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}

前端页面 (index.html)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>dchest/captcha Demo</title>
</head>
<body>
<h3>dchest/captcha Demo</h3>
<div>
<img id="captchaImg" style="border:1px solid #ccc;height:80px;" />
<button onclick="loadCaptcha()">刷新</button>
</div>
<div>
<input type="text" id="code" placeholder="输入验证码" />
<button onclick="verify()">验证</button>
</div>
<p id="result"></p>

<script>
let captchaId = "";

async function loadCaptcha() {
let res = await fetch("/captcha/generate");
let data = await res.json();
captchaId = data.id;
document.getElementById("captchaImg").src = "/captcha/image?id=" + captchaId + "&t=" + Date.now();
}

async function verify() {
let code = document.getElementById("code").value;
let res = await fetch("/captcha/verify", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({id: captchaId, code})
});
let data = await res.json();
document.getElementById("result").innerText = data.ok ? "✅ 成功" : "❌ 失败";
}

loadCaptcha();
</script>
</body>
</html>

🚀 Demo 2:使用 base64Captcha

后端代码 (main.go)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package main

import (
"encoding/json"
"log"
"net/http"

"github.com/mojocn/base64Captcha"
)

var store = base64Captcha.DefaultMemStore

func main() {
// 生成验证码
http.HandleFunc("/captcha/generate", func(w http.ResponseWriter, r *http.Request) {
driver := base64Captcha.NewDriverDigit(80, 240, 6, 0.7, 80)
c := base64Captcha.NewCaptcha(driver, store)
id, b64s, _, err := c.Generate()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
resp := map[string]string{"id": id, "image": b64s}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(resp)
})

// 校验验证码
http.HandleFunc("/captcha/verify", func(w http.ResponseWriter, r *http.Request) {
type req struct {
ID string `json:"id"`
Code string `json:"code"`
}
var in req
if err := json.NewDecoder(r.Body).Decode(&in); err != nil {
http.Error(w, "invalid body", http.StatusBadRequest)
return
}
ok := store.Verify(in.ID, in.Code, true)
resp := map[string]bool{"ok": ok}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(resp)
})

http.Handle("/", http.FileServer(http.Dir(".")))

log.Println("http://localhost:8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}

前端页面 (index.html)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>base64Captcha Demo</title>
</head>
<body>
<h3>base64Captcha Demo</h3>
<div>
<img id="captchaImg" style="border:1px solid #ccc;height:80px;" />
<button onclick="loadCaptcha()">刷新</button>
</div>
<div>
<input type="text" id="code" placeholder="输入验证码" />
<button onclick="verify()">验证</button>
</div>
<p id="result"></p>

<script>
let captchaId = "";

async function loadCaptcha() {
let res = await fetch("/captcha/generate");
let data = await res.json();
captchaId = data.id;
document.getElementById("captchaImg").src = data.image;
}

async function verify() {
let code = document.getElementById("code").value;
let res = await fetch("/captcha/verify", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({id: captchaId, code})
});
let data = await res.json();
document.getElementById("result").innerText = data.ok ? "✅ 成功" : "❌ 失败";
}

loadCaptcha();
</script>
</body>
</html>

🔹 如何运行

  1. 建一个文件夹,比如 captcha-demo

  2. 分别保存 main.goindex.html

  3. 执行:

    1
    go run main.go
  4. 打开浏览器访问:

    1
    http://localhost:8080/

    就能看到前端页面。


[up主专用,视频内嵌代码贴在这]