首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

ThinkPHP 6/8 驗證碼完整接入指南:控制器、模板、JS 刷新、多語言

     編輯:PHP 相關知識

環境準備

composer require topthink/think-captcha

控制器實現

<?php
namespace app\admin\controller;

use think\captcha\Captcha;
use think\Response;

class Login extends Base
{
    // 顯示登錄頁
    public function index(): Response
    {
        return $this->fetch();
    }

    // 生成驗證碼圖片
    public function captcha(): Response
    {
        $config = [
            'length'   => 4,          // 字符長度
            'width'    => 120,
            'height'   => 40,
            'fontSize' => 18,
            'useCurve' => true,       // 干擾曲線
            'useNoise' => true,       // 干擾點
            'expire'   => 1800,       // 30 分鐘有效
            'reset'    => true,       // 驗證後重置
        ];
        $captcha = new Captcha($config);
        return $captcha->entry(); // 直接輸出圖片響應
    }

    // 處理登錄提交
    public function doLogin()
    {
        $data = $this->request->post(['username', 'password', 'captcha']);
        
        // 1. 驗證碼校驗
        if (!captcha_check($data['captcha'])) {
            return json(['code' => 400, 'msg' => '驗證碼錯誤']);
        }

        // 2. 賬號密碼驗證(略)
        $user = User::where('username', $data['username'])->find();
        if (!$user || !password_verify($data['password'], $user->password)) {
            return json(['code' => 400, 'msg' => '用戶名或密碼錯誤']);
        }

        // 3. 寫入 Session、記住我 Token(略)
        session('admin_user', $user->toArray());
        
        return json(['code' => 200, 'msg' => '登錄成功', 'url' => url('index/index')]);
    }
}

模板文件

{-- resources/view/admin/login/index.html --}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>後台登錄</title>
    <script src="__STATIC__/js/jquery.min.js"></script>
</head>
<body>
<form id="loginForm">
    <div>
        <label>用戶名</label>
        <input name="username" type="text" required>
    </div>
    <div>
        <label>密碼</label>
        <input name="password" type="password" required>
    </div>
    <div>
        <label>驗證碼</label>
        <input name="captcha" type="text" required maxlength="4">
        <img id="captchaImg" src="{:captcha_src()}" alt="驗證碼" style="vertical-align:middle;cursor:pointer" title="點擊刷新">
    </div>
    <button type="submit">登錄</button>
</form>

<script>
    // 點擊圖片刷新
    $('#captchaImg').on('click', function() {
        this.src = '{:captcha_src()}' + '?' + Math.random();
    });

    // 表單提交
    $('#loginForm').on('submit', function(e) {
        e.preventDefault();
        $.post('{:url("admin/login/doLogin")}', $(this).serialize(), function(res) {
            if (res.code === 200) {
                location.href = res.url;
            } else {
                alert(res.msg);
                $('#captchaImg').trigger('click'); // 刷新驗證碼
            }
        }, 'json');
    });
</script>
</body>
</html>

配置文件

<?php
// config/captcha.php
return [
    // 默認配置(控制器可覆蓋)
    'length'   => 4,
    'width'    => 120,
    'height'   => 40,
    'fontSize' => 18,
    'useCurve' => true,
    'useNoise' => true,
    'expire'   => 1800,
    'reset'    => true,
    'fontttf'  => '1.ttf', // 字體文件放在 extend/think/captcha/assets/ttfs/
];

進階:算術驗證碼 / 中文驗證碼

// 算術類型:1+2=?
$captcha = new Captcha(['type' => 2]); // type=2 算術,type=1 字符(默認)

// 中文驗證碼:需自定義字符集
$captcha = new Captcha([
    'length' => 3,
    'charset' => '的一是不了人我在有他這為之大來以個中們', // 常用字
]);

API 端無狀態驗證(JWT + Redis)

// 獲取驗證碼 ID + 圖片 Base64
public function apiCaptcha()
{
    $id = \think\facade\String::uuid()->toString();
    $captcha = new Captcha(['reset' => false]);
    $code = $captcha->getCode(); // 獲取代碼不輸出圖片
    $img = $captcha->getImageBase64(); // Base64 圖片
    
    // 存 Redis,5 分鐘過期
    \think\facade\Cache::store('redis')->set("captcha:{$id}", strtolower($code), 300);
    
    return json(['id' => $id, 'image' => $img]);
}

// 驗證
public function apiVerify($id, $code)
{
    $stored = \think\facade\Cache::store('redis')->get("captcha:{$id}");
    if (!$stored || strtolower($code) !== $stored) {
        return json(['valid' => false]);
    }
    \think\facade\Cache::store('redis')->delete("captcha:{$id}");
    return json(['valid' => true]);
}

常見問題排查

現象原因解決
圖片顯示破圖/亂碼輸出前有空白/echo、BOM 頭ob_clean()、確保文件無 BOM、入口文件不輸出
驗證總是失敗Session 未啟動、域名不一致、大小寫啟用 Session、captcha_check 不區分大小寫、檢查 Cookie path
字體缺失報錯ttf 文件路徑錯誤將字體放入 extend/think/captcha/assets/ttfs/ 或配置絕對路徑
高併發下 Session 阻塞文件 Session 鎖競爭改用 Redis Session 驅動
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved