本文目录导读:

我将为您介绍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();
?>
注意事项
- 安全性:活体检测需要多层防护,包括设备检测、行为检测等
- 合规性:确保符合相关法律法规(如个人信息保护法)
- 性能优化:使用缓存、异步处理
- 降级处理:考虑网络异常、服务不可用等场景
- 数据安全:加密存储用户敏感信息
- 用户体验:合理设置超时和重试机制
建议优先使用专业服务商的服务,它们提供更准确、安全的活体检测功能。