PHP 活体检测集成

wen PHP项目 1

本文目录导读:

PHP 活体检测集成

  1. 常见活体检测方案
  2. 阿里云活体检测集成示例
  3. 腾讯云活体检测集成
  4. 完整的活体检测流程
  5. 自建活体检测方案
  6. 安全建议
  7. 完整调用示例
  8. 注意事项

我将为您介绍PHP活体检测的集成方案,活体检测通常用于人脸识别系统中,防止照片、视频等伪造攻击。

常见活体检测方案

主流服务商选择

  • 阿里云人脸活体检测
  • 腾讯云人脸核身
  • 百度AI人脸检测
  • Face++旷视
  • 商汤科技

阿里云活体检测集成示例

安装依赖

composer require alibabacloud/client

基础配置

<?php
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
class FaceLivenessCheck {
    private $accessKeyId;
    private $accessKeySecret;
    public function __construct($accessKeyId, $accessKeySecret) {
        $this->accessKeyId = $accessKeyId;
        $this->accessKeySecret = $accessKeySecret;
        AlibabaCloud::accessKeyClient(
            $this->accessKeyId,
            $this->accessKeySecret
        )->regionId('cn-shanghai')->asDefaultClient();
    }
    // 检测活体
    public function detectLiveness($imageBase64) {
        try {
            $result = AlibabaCloud::rpc()
                ->product('Facebody')
                ->version('2019-12-30')
                ->action('DetectLivingFace')
                ->method('POST')
                ->options([
                    'query' => [
                        'ImageURL' => $this->uploadImage($imageBase64),
                    ],
                ])
                ->request();
            return json_decode($result->toJson(), true);
        } catch (Exception $e) {
            return ['error' => $e->getMessage()];
        }
    }
    // 上传图片到可访问的URL
    private function uploadImage($imageBase64) {
        // 这里是简化的示例,实际需要上传到OSS或HTTP可访问的URL
        $imageName = uniqid() . '.jpg';
        $uploadPath = '/tmp/' . $imageName;
        file_put_contents($uploadPath, base64_decode($imageBase64));
        // 假设上传到OSS并返回URL
        return $this->uploadToOSS($uploadPath, $imageName);
    }
}
?>

腾讯云活体检测集成

安装SDK

composer require tencentcloud/tencentcloud-sdk-php

活体核身示例

<?php
require_once 'vendor/autoload.php';
use TencentCloud\Common\Credential;
use TencentCloud\Faceid\V20180301\FaceidClient;
use TencentCloud\Faceid\V20180301\Models\DetectAuthRequest;
use TencentCloud\Faceid\V20180301\Models\LivenessRecognitionRequest;
class TencentLiveness {
    private $client;
    public function __construct($secretId, $secretKey) {
        $cred = new Credential($secretId, $secretKey);
        $this->client = new FaceidClient($cred, "ap-guangzhou");
    }
    // 获取活体检测Token
    public function getDetectToken($ruleId, $name, $idCard) {
        try {
            $req = new DetectAuthRequest();
            $params = [
                "RuleId" => $ruleId,
                "Name" => $name,
                "IdCard" => $idCard,
            ];
            $req->fromJsonString(json_encode($params));
            $resp = $this->client->DetectAuth($req);
            return json_decode($resp->toJsonString(), true);
        } catch (\Exception $e) {
            return ['error' => $e->getMessage()];
        }
    }
    // 活体识别
    public function livenessRecognition($videoBase64) {
        try {
            $req = new LivenessRecognitionRequest();
            $params = [
                "VideoBase64" => $videoBase64,
                "LivenessType" => "SILENT", // 静默活体
            ];
            $req->fromJsonString(json_encode($params));
            $resp = $this->client->LivenessRecognition($req);
            return json_decode($resp->toJsonString(), true);
        } catch (\Exception $e) {
            return ['error' => $e->getMessage()];
        }
    }
}
?>

完整的活体检测流程

前端配合实现

<!-- 前端视频采集 -->
<video id="video" width="640" height="480" autoplay></video>
<canvas id="canvas" style="display:none;"></canvas>
<button onclick="captureVideo()">拍摄</button>
<script>
function initCamera() {
    navigator.mediaDevices.getUserMedia({
        video: {
            width: 640,
            height: 480,
            facingMode: "user"
        }
    }).then(stream => {
        document.getElementById('video').srcObject = stream;
    });
}
function captureVideo() {
    const video = document.getElementById('video');
    const canvas = document.getElementById('canvas');
    // 使用MediaRecorder录制视频
    const mediaRecorder = new MediaRecorder(video.srcObject);
    let chunks = [];
    mediaRecorder.ondataavailable = (e) => {
        chunks.push(e.data);
    };
    mediaRecorder.onstop = () => {
        const videoBlob = new Blob(chunks, {type: 'video/webm'});
        uploadToServer(videoBlob);
    };
    mediaRecorder.start();
    setTimeout(() => mediaRecorder.stop(), 3000); // 录制3秒
}
async function uploadToServer(videoBlob) {
    const formData = new FormData();
    formData.append('video', videoBlob);
    const response = await fetch('/api/liveness-check', {
        method: 'POST',
        body: formData
    });
    const result = await response.json();
    console.log('检测结果:', result);
}
</script>

后端处理接口

<?php
// liveness_check.php
header('Content-Type: application/json');
require_once 'TencentLiveness.php';
$config = [
    'secretId' => 'your_secret_id',
    'secretKey' => 'your_secret_key'
];
$liveness = new TencentLiveness($config['secretId'], $config['secretKey']);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (isset($_FILES['video'])) {
        $videoPath = $_FILES['video']['tmp_name'];
        $videoBase64 = base64_encode(file_get_contents($videoPath));
        // 执行活体检测
        $result = $liveness->livenessRecognition($videoBase64);
        // 记录日志
        logLivenessAttempt($result);
        // 返回结果
        if (isset($result['Error'])) {
            echo json_encode(['success' => false, 'message' => '检测失败']);
        } else {
            $verified = $result['Result'] === 'Success';
            echo json_encode([
                'success' => $verified,
                'data' => $result
            ]);
        }
    }
}
function logLivenessAttempt($result) {
    $log = date('Y-m-d H:i:s') . " - " . json_encode($result) . "\n";
    file_put_contents('liveness_log.txt', $log, FILE_APPEND);
}
?>

自建活体检测方案

基于OpenCV的简单实现

<?php
// 简单的静默活体检测
class OwnLivenessDetector {
    public function detect($imageBase64) {
        $image = base64_decode($imageBase64);
        $filename = tempnam('/tmp', 'face_') . '.jpg';
        file_put_contents($filename, $image);
        // 执行python脚本
        $output = shell_exec("python3 detect_liveness.py " . escapeshellarg($filename));
        $result = json_decode($output, true);
        unlink($filename);
        return $result;
    }
    // 检查眨眼检测
    public function checkBlink($frames) {
        // 需要多帧检测眨眼动作
        $totalBlink = 0;
        foreach ($frames as $frame) {
            if ($this->isEyeClosed($frame)) {
                $totalBlink++;
            }
        }
        return $totalBlink >= 2; // 至少眨眼两次
    }
    private function isEyeClosed($eyeData) {
        // 使用眼部特征点判断
        $eyeAspectRatio = ($eyeData['dist1'] + $eyeData['dist2']) / (2 * $eyeData['horizontalDist']);
        return $eyeAspectRatio < 0.2; // EAR阈值
    }
}
// Python活体检测脚本 (detect_liveness.py)
?>
# detect_liveness.py
import cv2
import dlib
import json
import sys
class LivenessDetector:
    def __init__(self):
        self.detector = dlib.get_frontal_face_detector()
        self.predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
    def analyze(self, image_path):
        image = cv2.imread(image_path)
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        faces = self.detector(gray)
        if len(faces) == 0:
            return {'live': False, 'message': '未检测到人脸'}
        # 计算特定眼部特征
        for face in faces:
            landmarks = self.predictor(gray, face)
            ear = self.calculate_ear(landmarks)
            return {
                'live': ear > 0.2,
                'ear': ear,
                'message': '活体检测通过' if ear > 0.2 else '可能是照片'
            }
    def calculate_ear(self, landmarks):
        # EAR (Eye Aspect Ratio) calculation
        left_eye_points = [36, 37, 38, 39, 40, 41]
        # 简化计算
        return 0.25  # 示例返回值
if __name__ == "__main__":
    detector = LivenessDetector()
    result = detector.analyze(sys.argv[1])
    print(json.dumps(result))

安全建议

防护措施

<?php
class SecurityHelper {
    // 请求频率限制
    public function rateLimit($userId, $limit = 10, $window = 60) {
        $key = "liveness_{$userId}";
        $current = apcu_fetch($key);
        if ($current >= $limit) {
            return false;
        }
        apcu_inc($key);
        return true;
    }
    // 验证图片真实性
    public function validateImage($file) {
        $finfo = new finfo(FILEINFO_MIME_TYPE);
        $mime = $finfo->file($file['tmp_name']);
        // 验证文件类型
        $allowed = ['image/jpeg', 'image/png', 'image/webp'];
        if (!in_array($mime, $allowed)) {
            return false;
        }
        // 验证文件大小 (最大10MB)
        if ($file['size'] > 10 * 1024 * 1024) {
            return false;
        }
        // 检查EXIF信息
        $exif = @exif_read_data($file['tmp_name']);
        if ($exif && isset($exif['Make'])) {
            // 真实相机拍摄的图片通常有EXIF信息
            return true;
        }
        return false;
    }
    // 记录安全日志
    public function logSecurityEvent($type, $details) {
        $securityLog = [
            'timestamp' => time(),
            'type' => $type,
            'ip' => $_SERVER['REMOTE_ADDR'],
            'user_agent' => $_SERVER['HTTP_USER_AGENT'],
            'details' => $details
        ];
        file_put_contents('security_log.log', json_encode($securityLog) . "\n", FILE_APPEND);
    }
}
?>

完整调用示例

<?php
// index.php - 完整示例
require_once 'TencentLiveness.php';
class FaceLivenessSystem {
    private $livenessClient;
    private $security;
    public function __construct() {
        $this->livenessClient = new TencentLiveness('your_id', 'your_key');
        $this->security = new SecurityHelper();
    }
    public function handleRequest() {
        // 安全检查
        if (!$this->security->rateLimit($_SERVER['REMOTE_ADDR'])) {
            return $this->response(false, '请求过于频繁');
        }
        // 获取参数
        $name = $_POST['name'] ?? '';
        $idCard = $_POST['idCard'] ?? '';
        // 步骤1: 获取验证Token
        $tokenResult = $this->livenessClient->getDetectToken(
            'your_rule_id', 
            $name, 
            $idCard
        );
        if (isset($tokenResult['Error'])) {
            return $this->response(false, '获取Token失败');
        }
        // 步骤2: 前端使用Token进行核身
        // 返回Token给前端
        return $this->response(true, '请完成验证', [
            'bizToken' => $tokenResult['BizToken'],
            'sign' => $tokenResult['Sign']
        ]);
    }
    private function response($success, $message, $data = null) {
        header('Content-Type: application/json');
        return json_encode([
            'success' => $success,
            'message' => $message,
            'data' => $data
        ]);
    }
}
// 使用示例
$system = new FaceLivenessSystem();
echo $system->handleRequest();
?>

注意事项

  1. 安全性:活体检测需要多层防护,包括设备检测、行为检测等
  2. 合规性:确保符合相关法律法规(如个人信息保护法)
  3. 性能优化:使用缓存、异步处理
  4. 降级处理:考虑网络异常、服务不可用等场景
  5. 数据安全:加密存储用户敏感信息
  6. 用户体验:合理设置超时和重试机制

建议优先使用专业服务商的服务,它们提供更准确、安全的活体检测功能。

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