mcpField
D
didit-liveness-detection

didit-liveness-detection

github.com/didit-protocol安全29228 次安装2 周前更新
代码仓库

关于 didit-liveness-detection

面向在身份验证中加入被动活体检测的开发者。它通过单张人脸图像评估用户是否为真人,无需视频或交互;也可保存结果并登记人脸,以供后续重复检测。

主要功能

  1. 01单张图像被动活体检测
  2. 02可配置的分数拒绝阈值
  3. 03人脸阻止名单与重复筛查
  4. 04可选保存会话并登记人脸
  5. 05响应中包含警告和判定状态

适用场景

  1. 01在用户注册时检测自拍
  2. 02识别身份验证中的呈现攻击
  3. 03将人脸与阻止名单及既往检测比对

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/didit-protocol/skills --skill didit-liveness-detection

安装后在 Claude Code 中输入/didit-liveness-detection确认已加载。

附带文件scripts/check_liveness.py

详细介绍

Didit 被动活体检测 API

概述

通过分析单张拍摄的图像,验证用户是否真实在场。无需视频、动作或用户交互。

主要限制:

  • 允许的文件扩展名:tiff、jpg、jpeg、png、webp(不支持 PDF)
  • 最大文件大小:5 MB(处理前会将图像压缩至约 0.5 MB,因此更高分辨率不会提高准确率)
  • 图像中须有一张清晰可见的人脸。若有多张人脸,则对最大的一张进行评分,并添加 MULTIPLE_FACES_DETECTED
  • 必须是原始实时拍摄的图像(不能使用屏幕截图、打印件或屏幕照片)

定价:$0.05(每次成功调用;单独调用不享受免费额度)。此为截至 2026 年 11 月 1 日的标价,届时 Didit 将调整定价:每月 500 次免费检查将变为每月 $10 免费额度。请访问 didit.me/pricing 查看当前价格。

**准确率:**活体检测准确率为 99.9%,误接受率(FAR)<0.1%。

**判定:**当任何 error 警告触发时(未检测到人脸、分数低于或等于阈值、呈现攻击、命中黑名单),status 为 Declined;否则为 Approved。此端点不会返回 In Review。只有分数阈值可配置。

**黑名单和重复筛查:**每次调用都会执行,save_api_request=false 时也不例外。系统会将人脸与应用的人脸搜索索引进行比对(包括人脸黑名单和白名单、已批准会话中的人脸、上传至用户个人资料的人脸,以及保留的生物特征模板)。重复检查时会跳过 vendor_data 相同的较早人脸,因此重新验证同一用户不会触发 DUPLICATED_FACE。若人脸在黑名单中,即使 vendor_data 相同,也仍会被检测到。若与人脸白名单匹配,则会抑制重复警告。

保存和录入(save_api_request,默认为 true):调用会保存为 API 会话(Business Console、GET /v3/session/{request_id}/decision/、status.updated webhook),并存储图像和人脸裁剪图;同时会将人脸录入人脸搜索索引,以便后续 Face Search 调用和重复检查能够匹配。设为 false 时不会存储任何内容,不会录入人脸,也无法查询 request_id。

**沙盒:**沙盒 API 密钥在请求验证后会返回固定的 Approved 负载;不会保存任何内容,也不会计费。

**活体检测方法:**此端点始终使用 PASSIVE(单帧 CNN)。托管工作流还可通过 face_liveness_method 工作流设置,使用 ACTIVE_3D(3D 动作与闪光,最高安全性)和 FLASHING(3D 闪光,高安全性)。

**API 参考:**https://docs.didit.me/standalone-apis/passive-liveness **功能指南:**https://docs.didit.me/core-technology/liveness/overview


身份验证

每个请求都需要 x-api-key 标头。请使用 Didit Business Console 中 Developers > API keys 下的应用 API 密钥,或通过编程方式创建账户和密钥(参见入门指南)。具有自定义访问权限的命名密钥需要具备 Sessions 写入权限,才能运行独立检查;仅限部分工作流或仅限已批准会话的密钥无法运行此类检查。

入门指南(还没有账户?)

如果你还没有 Didit API 密钥,只需调用 2 次 API 即可创建:

  1. **注册:**使用 {"email": "[email protected]", "password": "MyStr0ng!Pass"} 调用 POST https://apx.didit.me/auth/v2/programmatic/register/
  2. 查看电子邮件,获取 6 位验证码
  3. **验证:**使用 {"email": "[email protected]", "code": "A3K9F2"} 调用 POST https://apx.didit.me/auth/v2/programmatic/verify-email/。密钥位于响应中的 application.api_key。

**添加额度:**调用 GET /v3/billing/balance/ 查看余额,调用 POST /v3/billing/top-up/ 并传入 {"amount_in_dollars": 50} 获取 Stripe 结账链接。

如需全面的平台管理功能(工作流、会话、用户、账单),请参阅 didit-verification-management 技能。


端点

POST https://verification.didit.me/v3/passive-liveness/
请求头
请求头值必填
x-api-key你的 API 密钥是
Content-Typemultipart/form-data(由你的 HTTP 客户端设置)是
请求参数(multipart/form-data)
参数类型必填默认值约束描述
user_image文件是-tiff/jpg/jpeg/png/webp,最大 5 MB正面人脸图像(自拍照)
face_liveness_score_decline_threshold浮点数否300-100分数小于或等于此值时,会触发 LOW_LIVENESS_SCORE 并拒绝。提高此值可采取更严格的防伪措施
rotate_image布尔值否false-尝试旋转 90 度,并使用人脸检测效果最佳的方向。这会增加延迟
save_api_request布尔值否true-保存为 API 会话并录入人脸(参见概述)
vendor_data字符串否--你的用户标识符。该值会被存储并回传,也用于在人脸重复检查时跳过同一用户之前的人脸
metadataJSON 对象否-在 multipart 中以 JSON 编码字符串传递与会话一同存储(保存时)并回传
示例
import json

import requests

with open("selfie.jpg", "rb") as f:
    response = requests.post(
        "https://verification.didit.me/v3/passive-liveness/",
        headers={"x-api-key": "YOUR_API_KEY"},
        files={"user_image": ("selfie.jpg", f, "image/jpeg")},
        data={
            "face_liveness_score_decline_threshold": "50",
            "vendor_data": "user-123",
            "metadata": json.dumps({"flow": "withdrawal"}),
        },
        timeout=60,
    )
response.raise_for_status()
liveness = response.json()["liveness"]
print(liveness["status"], liveness["score"], [w["risk"] for w in liveness["warnings"]])
const formData = new FormData();
formData.append("user_image", selfieFile);
formData.append("face_liveness_score_decline_threshold", "50");
formData.append("vendor_data", "user-123");
formData.append("metadata", JSON.stringify({ flow: "withdrawal" }));

const response = await fetch("https://verification.didit.me/v3/passive-liveness/", {
  method: "POST",
  headers: { "x-api-key": "YOUR_API_KEY" },
  body: formData,
});
const { liveness } = await response.json();
响应(200 OK)
{
  "request_id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
  "liveness": {
    "status": "Approved",
    "method": "PASSIVE",
    "score": 95.0,
    "user_image": {
      "entities": [
        {"bbox": [661, 728, 1688, 2188], "confidence": 0.732973, "age": 26.91, "gender": "male"}
      ],
      "best_angle": 0
    },
    "warnings": [],
    "face_quality": 84.21,
    "face_luminance": 50.33
  },
  "vendor_data": "user-123",
  "metadata": {"flow": "withdrawal"},
  "created_at": "2026-06-12T01:04:42.763237+00:00"
}

即使人脸为伪造或在阻止名单中,仍会返回 HTTP 200:务必检查 liveness.status 和 liveness.warnings。

状态值与处理方式
状态含义操作
"Approved"未触发任何 error 警告继续处理。仍需检查 warnings 中是否有 DUPLICATED_FACE / POSSIBLE_DUPLICATED_FACE / MULTIPLE_FACES_DETECTED
"Declined"至少触发了一条 error 警告查看 warnings[].risk:采集问题应重新拍摄;攻击和阻止名单命中则应拦截或审核
错误响应
代码含义操作
400请求无效查看响应正文中的字段错误
400{"error": "Invalid user image format."}:文件扩展名虽允许,但无法解码文件将图像重新编码为 JPEG 或 PNG,然后重试
401API 密钥已过期轮换密钥,或在 Developers > API keys 中创建新密钥
403API 密钥缺失、错误或已撤销;受限密钥无权访问此端点;请求来自密钥 IP 允许列表之外;或额度不足查看 detail 或 error 中的消息:修正 x-api-key 请求头或密钥权限,或充值
429速率限制:每个密钥每分钟允许 300 次 POST/PATCH/DELETE 请求和 600 次 GET 请求等待 Retry-After 指定的秒数,然后重试

响应字段参考

字段类型描述
request_iduuid当 save_api_request=true 时为会话 ID(与 GET /v3/session/{request_id}/decision/ 配合使用);否则为一次性关联 ID
liveness.status字符串"Approved" 或 "Declined"
liveness.method字符串始终为 "PASSIVE"
liveness.score浮点数或 null0-100(保留两位小数),分数越高,越可能是真人。当模型未返回置信度时为 null;与阈值比较时,null 分数按 0 计算
liveness.user_image.entities[]数组每张检测到的人脸对应一条记录:bbox [x_min, y_min, x_max, y_max]、confidence(0-1)、age、gender。年龄和性别仅供参考,不影响判定
liveness.user_image.best_angle整数或 null检测效果最佳时的旋转角度(度);仅当 rotate_image=true 且旋转进行了校正时才为非零值
liveness.warnings[]数组{risk, feature, additional_data, log_type, short_description, long_description}。feature 始终为 LIVENESS
liveness.face_quality浮点数或 null人脸的采集质量,范围为 0-100。无可靠值时为 null
liveness.face_luminance浮点数或 null人脸亮度,范围为 0-100。不可用时为 null
vendor_data字符串或 null回传你发送的内容
metadata对象或 null回传你发送的内容
created_at字符串响应时间,采用 ISO 8601 UTC 格式

警告标签

标签严重性是否拒绝触发条件
NO_FACE_DETECTEDerror是活体检测模型未检测到人脸
LOW_LIVENESS_SCOREerror是score 小于或等于 face_liveness_score_decline_threshold。不会与 NO_FACE_DETECTED 同时触发
LIVENESS_FACE_ATTACKerror是检测到呈现攻击(打印照片、屏幕回放、面具、深度伪造)
FACE_IN_BLOCKLISTerror是与人脸屏蔽名单中的某张人脸高度匹配。additional_data 包含 blocklisted_session_id、blocklisted_session_number、api_service
POSSIBLE_FACE_IN_BLOCKLISTerror是与屏蔽名单中的某张人脸较弱匹配。此端点会拒绝该请求(工作流会将其送审)
MULTIPLE_FACES_DETECTEDwarning否检测到多张人脸;系统对最大的人脸进行评分
DUPLICATED_FACEinformation否与另一已通过审核的会话中的人脸(或导入的人脸、保留的模板)高度匹配。additional_data 包含 duplicated_session_id、duplicated_session_number、api_service
POSSIBLE_DUPLICATED_FACEinformation否同类人脸较弱匹配
  • 此端点不会触发 LOW_FACE_QUALITY、LOW_FACE_LUMINANCE 和 HIGH_FACE_LUMINANCE(这些是工作流警告)。如需判断,请自行设置 face_quality / face_luminance 规则。
  • 请根据 status 和 warnings[].risk 做出判断。以上严重性是此端点的规则;将每条警告中回显的 log_type 视为信息即可。

常见工作流

基本人脸活体检测
1. Capture the user's selfie
2. POST /v3/passive-liveness/ with user_image and vendor_data=<your user id>
3. "Approved" -> the user is live, proceed
   "Declined" -> check warnings[].risk:
     NO_FACE_DETECTED / LOW_LIVENESS_SCORE -> ask for a retake: one well-lit, centered face
     LIVENESS_FACE_ATTACK                  -> suspected spoof, do not approve
     FACE_IN_BLOCKLIST / POSSIBLE_FACE_IN_BLOCKLIST -> block or send to manual review
4. "Approved" with DUPLICATED_FACE -> this face already passed under another vendor_data:
   look up additional_data.duplicated_session_id before creating a new account
活体检测 + 人脸匹配(组合)
1. POST /v3/passive-liveness/ -> verify the selfie is live
2. If Approved -> POST /v3/face-match/ with user_image=selfie, ref_image=ID portrait
3. Both Approved -> the live person matches the document photo

需要按相似度列出所有人脸,而不是获取屏蔽名单/重复人脸判定结果?请使用 didit-face-search 技能,并在此处保存同一张自拍照之前运行它(已保存的活体检测人脸本身也可搜索)。


实用脚本

export DIDIT_API_KEY="your_api_key"

python scripts/check_liveness.py selfie.jpg
python scripts/check_liveness.py selfie.jpg --threshold 50 --vendor-data user-123
python scripts/check_liveness.py selfie.jpg --rotate --no-save --metadata '{"flow": "withdrawal"}'

评论

支持 Markdown