PHP 人脸识别认证

wen PHP项目 2

我将为您提供一个完整的PHP人脸识别认证系统实现方案,这个系统将使用百度AI开放平台提供的人脸识别API。

PHP 人脸识别认证

完整的人脸识别认证系统

系统架构

项目结构:
├── config/
│   └── config.php          # 配置文件
├── includes/
│   ├── FaceAuth.php        # 人脸认证核心类
│   ├── Database.php        # 数据库操作类
│   └── ImageUpload.php     # 图片上传处理类
├── uploads/                # 上传图片目录
├── register.php            # 人脸注册页面
├── login.php               # 人脸登录页面
├── auth_callback.php       # 认证回调处理
└── database.sql            # 数据库结构

数据库结构

-- database.sql
CREATE DATABASE IF NOT EXISTS face_auth_system;
USE face_auth_system;
-- 用户表
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) UNIQUE NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    face_token VARCHAR(100) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    last_login TIMESTAMP NULL
);
-- 认证记录表
CREATE TABLE auth_logs (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user_id INT,
    auth_type ENUM('register', 'login', 'verify') NOT NULL,
    result ENUM('success', 'failed') NOT NULL,
    score FLOAT,
    ip_address VARCHAR(45),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
);

配置文件

<?php
// config/config.php
// 数据库配置
define('DB_HOST', 'localhost');
define('DB_NAME', 'face_auth_system');
define('DB_USER', 'root');
define('DB_PASS', '');
// 百度AI配置
define('BAIDU_APP_ID', '你的App ID');
define('BAIDU_API_KEY', '你的API Key');
define('BAIDU_SECRET_KEY', '你的Secret Key');
define('BAIDU_ACCESS_TOKEN_URL', 'https://aip.baidubce.com/oauth/2.0/token');
define('BAIDU_GROUP_ID', 'your_face_group');
// 系统配置
define('FACE_AUTH_THRESHOLD', 80); // 人脸认证准确率阈值
define('MAX_IMAGE_SIZE', 10 * 1024 * 1024); // 10MB
// 获取百度AI Access Token
function getBaiduAccessToken() {
    $url = BAIDU_ACCESS_TOKEN_URL . '?grant_type=client_credentials&client_id=' . 
           BAIDU_API_KEY . '&client_secret=' . BAIDU_SECRET_KEY;
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($ch);
    curl_close($ch);
    $data = json_decode($response, true);
    return $data['access_token'];
}
?>

核心类 - 人脸认证

<?php
// includes/FaceAuth.php
class FaceAuth {
    private $accessToken;
    private $appId;
    private $apiUrl;
    public function __construct() {
        $this->appId = BAIDU_APP_ID;
        $this->accessToken = getBaiduAccessToken();
        $this->apiUrl = 'https://aip.baidubce.com/rest/2.0/face/v3/';
    }
    /**
     * 人脸注册
     * @param string $imageBase64 - 人脸图片Base64编码
     * @param string $userId - 用户ID
     * @return array - 返回face_token等信息
     */
    public function faceRegister($imageBase64, $userId) {
        $url = $this->apiUrl . 'face/add?access_token=' . $this->accessToken;
        $params = [
            'image' => $imageBase64,
            'image_type' => 'BASE64',
            'group_id' => BAIDU_GROUP_ID,
            'user_id' => $userId,
            'user_info' => 'User registration at ' . date('Y-m-d H:i:s')
        ];
        $result = $this->curlPost($url, $params);
        return $result;
    }
    /**
     * 人脸搜索(认证登录)
     * @param string $imageBase64 - 待认证人脸图片
     * @return array - 返回匹配结果
     */
    public function faceSearch($imageBase64) {
        $url = $this->apiUrl . 'search?access_token=' . $this->accessToken;
        $params = [
            'image' => $imageBase64,
            'image_type' => 'BASE64',
            'group_id_list' => BAIDU_GROUP_ID,
            'quality_control' => 'NORMAL',
            'liveness_control' => 'NONE'
        ];
        $result = $this->curlPost($url, $params);
        return $result;
    }
    /**
     * 人脸比对
     * @param string $image1 - 第一张人脸图
     * @param string $image2 - 第二张人脸图
     * @return array - 返回相似度分数
     */
    public function faceCompare($image1, $image2) {
        $url = $this->apiUrl . 'match?access_token=' . $this->accessToken;
        $params = [
            [
                'image' => $image1,
                'image_type' => 'BASE64'
            ],
            [
                'image' => $image2,
                'image_type' => 'BASE64'
            ]
        ];
        $result = $this->curlPost($url, $params);
        return $result;
    }
    /**
     * 检测人脸质量
     * @param string $imageBase64 - 人脸图片
     * @return array - 返回人脸质量评估结果
     */
    public function faceDetect($imageBase64) {
        $url = $this->apiUrl . 'detect?access_token=' . $this->accessToken;
        $params = [
            'image' => $imageBase64,
            'image_type' => 'BASE64',
            'face_field' => 'quality,angle,beauty,age,gender'
        ];
        $result = $this->curlPost($url, $params);
        return $result;
    }
    /**
     * 更新用户人脸
     * @param string $imageBase64 - 新的人脸图片
     * @param string $faceToken - 原人脸token
     * @param string $userId - 用户ID
     * @return array
     */
    public function faceUpdate($imageBase64, $faceToken, $userId) {
        $url = $this->apiUrl . 'face/update?access_token=' . $this->accessToken;
        $params = [
            'image' => $imageBase64,
            'image_type' => 'BASE64',
            'group_id' => BAIDU_GROUP_ID,
            'user_id' => $userId,
            'face_token' => $faceToken
        ];
        $result = $this->curlPost($url, $params);
        return $result;
    }
    /**
     * 删除用户人脸
     * @param string $faceToken - 人脸token
     * @param string $userId - 用户ID
     * @return array
     */
    public function faceDelete($faceToken, $userId) {
        $url = $this->apiUrl . 'face/delete?access_token=' . $this->accessToken;
        $params = [
            'face_token' => $faceToken,
            'group_id' => BAIDU_GROUP_ID,
            'user_id' => $userId
        ];
        $result = $this->curlPost($url, $params);
        return $result;
    }
    /**
     * 获取用户信息
     * @param string $userId - 用户ID
     * @return array
     */
    public function getUserInfo($userId) {
        $url = $this->apiUrl . 'user/get?access_token=' . $this->accessToken;
        $params = [
            'group_id' => BAIDU_GROUP_ID,
            'user_id' => $userId
        ];
        $result = $this->curlPost($url, $params);
        return $result;
    }
    /**
     * 人脸活体检测
     * @param string $imageBase64 - 人脸图片
     * @param string $faceFields - 需要返回的属性
     * @return array
     */
    public function faceLiveness($imageBase64, $faceFields = 'quality,faceliveness') {
        $url = $this->apiUrl . 'liveness?access_token=' . $this->accessToken;
        $params = [
            'image' => $imageBase64,
            'image_type' => 'BASE64',
            'face_field' => $faceFields
        ];
        $result = $this->curlPost($url, $params);
        return $result;
    }
    private function curlPost($url, $data) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/x-www-form-urlencoded'
        ]);
        $response = curl_exec($ch);
        curl_close($ch);
        return json_decode($response, true);
    }
    /**
     * 验证人脸认证结果
     * @param array $result - 百度API返回结果
     * @param float $threshold - 准确率阈值
     * @return array - 认证结果
     */
    public function validateAuthResult($result, $threshold = null) {
        if ($threshold === null) {
            $threshold = FACE_AUTH_THRESHOLD;
        }
        if (isset($result['error_code']) && $result['error_code'] !== 0) {
            return [
                'success' => false,
                'error' => $result['error_msg']
            ];
        }
        if (isset($result['result']['user_list'][0])) {
            $userInfo = $result['result']['user_list'][0];
            $score = $userInfo['score'];
            if ($score >= $threshold) {
                return [
                    'success' => true,
                    'score' => $score,
                    'user_id' => $userInfo['user_id'],
                    'face_token' => $userInfo['face_token']
                ];
            } else {
                return [
                    'success' => false,
                    'error' => '认证准确率不足,当前为:' . $score . '%,需要达到' . $threshold . '%以上',
                    'score' => $score
                ];
            }
        }
        return [
            'success' => false,
            'error' => '未找到匹配的人脸信息'
        ];
    }
}
?>

数据库操作类

<?php
// includes/Database.php
class Database {
    private $host;
    private $dbName;
    private $username;
    private $password;
    private $connection;
    private static $instance = null;
    private function __construct() {
        $this->host = DB_HOST;
        $this->dbName = DB_NAME;
        $this->username = DB_USER;
        $this->password = DB_PASS;
        $this->connect();
    }
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new Database();
        }
        return self::$instance;
    }
    private function connect() {
        try {
            $dsn = "mysql:host={$this->host};dbname={$this->dbName};charset=utf8mb4";
            $this->connection = new PDO($dsn, $this->username, $this->password);
            $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch (PDOException $e) {
            die("数据库连接失败: " . $e->getMessage());
        }
    }
    public function getConnection() {
        return $this->connection;
    }
    public function insertUser($username, $email, $faceToken) {
        $sql = "INSERT INTO users (username, email, face_token) VALUES (?, ?, ?)";
        $stmt = $this->connection->prepare($sql);
        $result = $stmt->execute([$username, $email, $faceToken]);
        return $result ? $this->connection->lastInsertId() : false;
    }
    public function getUserByFaceToken($faceToken) {
        $sql = "SELECT * FROM users WHERE face_token = ?";
        $stmt = $this->connection->prepare($sql);
        $stmt->execute([$faceToken]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
    public function getUserByUsername($username) {
        $sql = "SELECT * FROM users WHERE username = ?";
        $stmt = $this->connection->prepare($sql);
        $stmt->execute([$username]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
    public function logAuthAttempt($userId, $authType, $result, $score = null) {
        $ipAddress = $_SERVER['REMOTE_ADDR'];
        $sql = "INSERT INTO auth_logs (user_id, auth_type, result, score, ip_address) 
                VALUES (?, ?, ?, ?, ?)";
        $stmt = $this->connection->prepare($sql);
        return $stmt->execute([$userId, $authType, $result, $score, $ipAddress]);
    }
}
?>

注册页面

<?php
// register.php
session_start();
require_once 'config/config.php';
require_once 'includes/Database.php';
require_once 'includes/FaceAuth.php';
$db = Database::getInstance()->getConnection();
$faceAuth = new FaceAuth();
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // 获取表单数据
    $username = trim($_POST['username']);
    $email = trim($_POST['email']);
    $password = $_POST['password'];
    $confirmPassword = $_POST['confirm_password'];
    // 检查用户名和邮箱是否已存在
    $stmt = $db->prepare("SELECT id FROM users WHERE username = ? OR email = ?");
    $stmt->execute([$username, $email]);
    if ($stmt->fetch()) {
        $errors[] = "用户名或邮箱已被注册";
    }
    // 验证密码
    if ($password !== $confirmPassword) {
        $errors[] = "两次输入密码不一致";
    }
    // 处理人脸图片上传
    if (isset($_FILES['face_image']) && $_FILES['face_image']['error'] === UPLOAD_ERR_OK) {
        try {
            // 验证图片
            if ($_FILES['face_image']['size'] > MAX_IMAGE_SIZE) {
                throw new Exception("图片大小不能超过10MB");
            }
            // 转为Base64
            $imageContent = file_get_contents($_FILES['face_image']['tmp_name']);
            $base64Image = base64_encode($imageContent);
            // 进行人脸检测,确保图片中有人脸
            $detectResult = $faceAuth->faceDetect($base64Image);
            if (isset($detectResult['error_code']) && $detectResult['error_code'] !== 0) {
                throw new Exception("人脸检测失败: " . $detectResult['error_msg']);
            }
            if ($detectResult['result']['face_num'] === 0) {
                throw new Exception("图片中没有检测到人脸");
            }
            // 检查人脸质量
            $faceQuality = $detectResult['result']['face_list'][0]['quality'];
            if ($faceQuality['blur'] > 0.8 || $faceQuality['illumination'] < 0.5) {
                throw new Exception("人脸图片质量不佳,请更换照片");
            }
            // 生成唯一用户ID
            $userId = md5(uniqid() . time());
            // 注册人脸
            $registerResult = $faceAuth->faceRegister($base64Image, $userId);
            if (isset($registerResult['error_code']) && $registerResult['error_code'] !== 0) {
                throw new Exception("人脸注册失败: " . $registerResult['error_msg']);
            }
            $faceToken = $registerResult['result']['face_token'];
            // 保存用户信息
            $hashedPassword = password_hash($password, PASSWORD_DEFAULT);
            $sql = "INSERT INTO users (username, email, face_token, user_id) VALUES (?, ?, ?, ?)";
            $stmt = $db->prepare($sql);
            $stmt->execute([$username, $email, $faceToken, $userId]);
            // 记录注册日志
            $db->prepare("INSERT INTO auth_logs (user_id, auth_type, result) VALUES (?, 'register', 'success')")
               ->execute([$userId]);
            $_SESSION['success'] = "注册成功!请使用人脸识别登录";
            header('Location: login.php');
            exit();
        } catch (Exception $e) {
            $errors[] = $e->getMessage();
        }
    } else {
        $errors[] = "请上传人脸图片";
    }
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">人脸识别注册</title>
    <style>
        .container { max-width: 600px; margin: 50px auto; padding: 20px; }
        .form-group { margin-bottom: 20px; }
        .form-group label { display: block; margin-bottom: 5px; }
        .form-group input { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; }
        .error { color: red; margin-bottom: 10px; }
        .success { color: green; margin-bottom: 10px; }
        #camera-preview { width: 300px; height: 300px; margin: 10px 0; }
    </style>
</head>
<body>
    <div class="container">
        <h2>人脸识别注册</h2>
        <?php if (!empty($errors)): ?>
            <div class="error">
                <?php foreach ($errors as $error): ?>
                    <p><?php echo htmlspecialchars($error); ?></p>
                <?php endforeach; ?>
            </div>
        <?php endif; ?>
        <?php if (isset($_SESSION['success'])): ?>
            <div class="success"><?php echo $_SESSION['success']; ?></div>
        <?php endif; ?>
        <form method="POST" enctype="multipart/form-data">
            <div class="form-group">
                <label>用户名</label>
                <input type="text" name="username" required>
            </div>
            <div class="form-group">
                <label>邮箱</label>
                <input type="email" name="email" required>
            </div>
            <div class="form-group">
                <label>密码</label>
                <input type="password" name="password" required>
            </div>
            <div class="form-group">
                <label>确认密码</label>
                <input type="password" name="confirm_password" required>
            </div>
            <div class="form-group">
                <label>人脸图片</label>
                <input type="file" name="face_image" accept="image/*" capture="user" required>
            </div>
            <div class="form-group">
                <label>拍照或上传照片</label>
                <button type="button" id="camera-button">打开摄像头</button>
                <video id="camera-preview" autoplay playsinline style="display:none;"></video>
                <canvas id="face-capture" style="display:none;"></canvas>
            </div>
            <button type="submit">注册</button>
        </form>
        <p>已有账号?<a href="login.php">登录</a></p>
    </div>
    <script>
    // 摄像头拍照功能
    const cameraButton = document.getElementById('camera-button');
    const preview = document.getElementById('camera-preview');
    const canvas = document.getElementById('face-capture');
    const fileInput = document.querySelector('input[name="face_image"]');
    cameraButton.addEventListener('click', async () => {
        try {
            const stream = await navigator.mediaDevices.getUserMedia({ video: true });
            preview.srcObject = stream;
            preview.style.display = 'block';
            // 3秒后自动拍照
            setTimeout(() => {
                canvas.width = preview.videoWidth;
                canvas.height = preview.videoHeight;
                canvas.getContext('2d').drawImage(preview, 0, 0);
                // 停止摄像头
                stream.getTracks().forEach(track => track.stop());
                preview.style.display = 'none';
                // 将canvas转为文件
                canvas.toBlob(blob => {
                    const file = new File([blob], 'face.png', { type: 'image/png' });
                    const dt = new DataTransfer();
                    dt.items.add(file);
                    fileInput.files = dt.files;
                }, 'image/png');
            }, 3000);
        } catch (error) {
            console.error('摄像头访问失败:', error);
            alert('无法访问摄像头,请使用文件上传');
        }
    });
    </script>
</body>
</html>

登录认证页面

<?php
// login.php
session_start();
require_once 'config/config.php';
require_once 'includes/Database.php';
require_once 'includes/FaceAuth.php';
$db = Database::getInstance()->getConnection();
$faceAuth = new FaceAuth();
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (isset($_POST['face_data'])) {
        // 人脸识别登录
        $base64Image = $_POST['face_data'];
        // 执行人脸搜索
        $searchResult = $faceAuth->faceSearch($base64Image);
        // 验证认证结果
        $authResult = $faceAuth->validateAuthResult($searchResult);
        if ($authResult['success']) {
            // 获取用户信息
            $stmt = $db->prepare("SELECT * FROM users WHERE user_id = ?");
            $stmt->execute([$authResult['user_id']]);
            $user = $stmt->fetch(PDO::FETCH_ASSOC);
            if ($user) {
                // 更新最后登录时间
                $db->prepare("UPDATE users SET last_login = NOW() WHERE id = ?")
                   ->execute([$user['id']]);
                // 记录认证日志
                $db->prepare("INSERT INTO auth_logs (user_id, auth_type, result, score) 
                             VALUES (?, 'login', 'success', ?)")
                   ->execute([$user['id'], $authResult['score']]);
                // 设置会话
                $_SESSION['user_id'] = $user['id'];
                $_SESSION['username'] = $user['username'];
                $_SESSION['face_auth'] = true;
                header('Location: dashboard.php');
                exit();
            }
        } else {
            $errors[] = $authResult['error'];
        }
    } else {
        $errors[] = "请进行人脸识别或输入密码";
    }
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">人脸识别登录</title>
    <style>
        .container { max-width: 600px; margin: 50px auto; padding: 20px; }
        #camera { width: 100%; max-width: 400px; height: 300px; margin: 10px 0; }
        .btn { padding: 10px 20px; margin: 5px; }
        .preview { width: 300px; height: 300px; margin: 10px 0; }
        .error { color: red; margin-bottom: 10px; }
    </style>
</head>
<body>
    <div class="container">
        <h2>人脸识别登录</h2>
        <?php if (!empty($errors)): ?>
            <div class="error">
                <?php foreach ($errors as $error): ?>
                    <p><?php echo htmlspecialchars($error); ?></p>
                <?php endforeach; ?>
            </div>
        <?php endif; ?>
        <div id="camera">
            <video id="video" width="300" height="300" autoplay playsinline></video>
            <canvas id="canvas" width="300" height="300" style="display:none;"></canvas>
        </div>
        <button id="start-camera" class="btn">开启摄像头</button>
        <button id="capture-face" class="btn">拍照识别</button>
        <form method="POST" id="login-form">
            <input type="hidden" name="face_data" id="face-data">
        </form>
        <!-- 或者使用文件上传方式 -->
        <hr>
        <h3>或者上传照片</h3>
        <form method="POST" enctype="multipart/form-data">
            <input type="file" name="face_image" accept="image/*" capture="user">
            <button type="submit" class="btn">上传识别</button>
        </form>
        <p>还没有账号?<a href="register.php">注册</a></p>
    </div>
    <script>
    let stream = null;
    const video = document.getElementById('video');
    const canvas = document.getElementById('canvas');
    document.getElementById('start-camera').addEventListener('click', async () => {
        try {
            stream = await navigator.mediaDevices.getUserMedia({ video: true });
            video.srcObject = stream;
            video.style.display = 'block';
        } catch (error) {
            console.error('摄像头错误:', error);
            alert('无法访问摄像头');
        }
    });
    document.getElementById('capture-face').addEventListener('click', () => {
        canvas.getContext('2d').drawImage(video, 0, 0, 300, 300);
        const dataUrl = canvas.toDataURL('image/jpeg', 0.9);
        // 移除data:image/jpeg;base64,前缀
        const base64 = dataUrl.split(',')[1];
        document.getElementById('face-data').value = base64;
        document.getElementById('login-form').submit();
    });
    // 文件上传方式
    document.querySelector('input[name="face_image"]').addEventListener('change', function() {
        if (this.files.length > 0) {
            this.form.submit();
        }
    });
    </script>
</body>
</html>

认证回调处理

<?php
// auth_callback.php
require_once 'config/config.php';
require_once 'includes/Database.php';
require_once 'includes/FaceAuth.php';
session_start();
header('Content-Type: application/json');
$db = Database::getInstance()->getConnection();
$faceAuth = new FaceAuth();
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    echo json_encode(['success' => false, 'message' => '无效请求']);
    exit();
}
try {
    // 获取请求类型
    $action = $_POST['action'] ?? 'search';
    switch ($action) {
        case 'search':
            // 人脸搜索认证
            $imageBase64 = $_POST['image_base64'] ?? '';
            if (empty($imageBase64)) {
                throw new Exception('缺少图片数据');
            }
            $result = $faceAuth->faceSearch($imageBase64);
            $authResult = $faceAuth->validateAuthResult($result);
            if ($authResult['success']) {
                // 获取用户信息
                $stmt = $db->prepare("SELECT * FROM users WHERE user_id = ?");
                $stmt->execute([$authResult['user_id']]);
                $user = $stmt->fetch(PDO::FETCH_ASSOC);
                if ($user) {
                    // 更新最后登录时间
                    $db->prepare("UPDATE users SET last_login = NOW() WHERE id = ?")
                       ->execute([$user['id']]);
                    // 记录日志
                    $db->prepare("INSERT INTO auth_logs (user_id, auth_type, result, score, ip_address) 
                                 VALUES (?, 'login', 'success', ?, ?)")
                       ->execute([$user['id'], $authResult['score'], $_SERVER['REMOTE_ADDR']]);
                    // 创建会话
                    $_SESSION['user_id'] = $user['id'];
                    $_SESSION['username'] = $user['username'];
                    $_SESSION['face_auth'] = true;
                    echo json_encode([
                        'success' => true,
                        'message' => '人脸识别成功',
                        'score' => $authResult['score'],
                        'user' => [
                            'id' => $user['id'],
                            'username' => $user['username'],
                            'email' => $user['email']
                        ]
                    ]);
                } else {
                    throw new Exception('用户不存在');
                }
            } else {
                // 记录失败日志
                $db->prepare("INSERT INTO auth_logs (auth_type, result, score, ip_address) 
                             VALUES ('login', 'failed', ?, ?)")
                   ->execute([$authResult['score'] ?? 0, $_SERVER['REMOTE_ADDR']]);
                throw new Exception($authResult['error']);
            }
            break;
        case 'detect':
            // 人脸检测
            $imageBase64 = $_POST['image_base64'] ?? '';
            if (empty($imageBase64)) {
                throw new Exception('缺少图片数据');
            }
            $result = $faceAuth->faceDetect($imageBase64);
            echo json_encode($result);
            break;
        case 'compare':
            // 人脸比对
            $image1 = $_POST['image1'] ?? '';
            $image2 = $_POST['image2'] ?? '';
            if (empty($image1) || empty($image2)) {
                throw new Exception('缺少比对图片数据');
            }
            $result = $faceAuth->faceCompare($image1, $image2);
            echo json_encode($result);
            break;
        default:
            throw new Exception('无效操作类型');
    }
} catch (Exception $e) {
    echo json_encode([
        'success' => false,
        'message' => $e->getMessage()
    ]);
}
?>

用户仪表盘页面

<?php
// dashboard.php
session_start();
// 检查认证状态
if (!isset($_SESSION['user_id'])) {
    header('Location: login.php');
    exit();
}
require_once 'config/config.php';
require_once 'includes/Database.php';
$db = Database::getInstance()->getConnection();
// 获取用户信息
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$user) {
    session_destroy();
    header('Location: login.php');
    exit();
}
// 获取认证日志
$stmt = $db->prepare("SELECT * FROM auth_logs WHERE user_id = ? ORDER BY created_at DESC LIMIT 10");
$stmt->execute([$_SESSION['user_id']]);
$logs = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">用户仪表盘</title>
    <style>
        .container { max-width: 800px; margin: 50px auto; padding: 20px; }
        .user-info { background: #f5f5f5; padding: 20px; border-radius: 5px; }
        .logs { margin-top: 30px; }
        table { width: 100%; border-collapse: collapse; }
        th, td { padding: 10px; border: 1px solid #ddd; text-align: left; }
        .logout { float: right; }
    </style>
</head>
<body>
    <div class="container">
        <div class="user-info">
            <h2>欢迎, <?php echo htmlspecialchars($user['username']); ?>!</h2>
            <p>邮箱: <?php echo htmlspecialchars($user['email']); ?></p>
            <p>注册时间: <?php echo $user['created_at']; ?></p>
            <p>最后登录: <?php echo $user['last_login']; ?></p>
            <form method="POST" action="logout.php">
                <button type="submit" class="logout">退出登录</button>
            </form>
        </div>
        <div class="logs">
            <h3>最近认证记录</h3>
            <table>
                <thead>
                    <tr>
                        <th>时间</th>
                        <th>类型</th>
                        <th>结果</th>
                        <th>准确率</th>
                        <th>IP地址</th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach ($logs as $log): ?>
                    <tr>
                        <td><?php echo $log['created_at']; ?></td>
                        <td><?php echo $log['auth_type']; ?></td>
                        <td><?php echo $log['result']; ?></td>
                        <td><?php echo $log['score'] ? number_format($log['score'], 2) . '%' : '-'; ?></td>
                        <td><?php echo $log['ip_address']; ?></td>
                    </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>
        </div>
    </div>
</body>
</html>

认证验证中间件

<?php
// includes/AuthMiddleware.php
class AuthMiddleware {
    private $db;
    public function __construct() {
        $this->db = Database::getInstance()->getConnection();
    }
    /**
     * 会话认证令牌验证
     */
    public function validateSession() {
        if (!isset($_SESSION['user_id'])) {
            header('Location: login.php');
            exit();
        }
        // 验证会话是否有效
        $token = $_SESSION['auth_token'] ?? null;
        if (!$token) {
            $this->logout();
            header('Location: login.php');
            exit();
        }
    }
    /**
     * 生成认证令牌
     */
    public function generateAuthToken($userId) {
        $token = bin2hex(random_bytes(32));
        $sql = "INSERT INTO auth_tokens (user_id, token, expires_at) VALUES (?, ?, DATE_ADD(NOW(), INTERVAL 1 HOUR))";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([$userId, $token]);
        return $token;
    }
    /**
     * 验证认证令牌
     */
    public function validateAuthToken($token, $userId = null) {
        $sql = "SELECT * FROM auth_tokens WHERE token = ? AND expires_at > NOW()";
        if ($userId) {
            $sql .= " AND user_id = ?";
        }
        $stmt = $this->db->prepare($sql);
        $stmt->execute($userId ? [$token, $userId] : [$token]);
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        return $result ? true : false;
    }
    /**
     * 双因素认证检查
     */
    public function checkTwoFactor($userId) {

抱歉,评论功能暂时关闭!