问题的另一面:识别准确不等于数据可信
上一篇文章我们解决了隐私合规问题——人脸数据本地处理、用完即毁。但运行一段时间后,新的问题浮出水面:考勤数据本身不可信。
我们做了几组模拟测试:用手机屏幕播放一段学生视频对着摄像头,系统居然识别成功了。打印一张学生的照片放在镜头前,同样“签到成功”。这意味着什么?意味着学生完全可以委托同学拿着自己的照片来代打卡,而系统毫无察觉。
更严重的是数据篡改问题。传统考勤系统用中心化数据库存储记录,管理员可以随意增删改。学校应付检查可以伪造数据,学生缺勤可以花钱找人改记录——这些都不是假设,是真实发生过的事。
所以我们面临两个问题:
-
前端:怎么防止照片/视频代打卡?
-
后端:怎么让考勤记录不可篡改、可追溯?
零额外开销的活体检测:多帧时序一致性
先解决第一个问题。市面上很多活体检测方案需要额外硬件——比如红外摄像头、3D结构光传感器。但我们的目标设备是普通USB摄像头,加硬件意味着加成本,和“低成本部署”的理念冲突。
我们设计了一个纯软件的活体检测算法,核心观察是:真人脸在连续帧之间会产生微小运动(呼吸、微表情、头部晃动),而照片或视频回放是静态的。
实现方案:
python
# 为每个跟踪目标维护一个5帧特征滑动窗口
window_size = 5
motion_threshold = 0.05
# 计算相邻帧特征向量之间的欧氏距离差异
avg_diff = mean([dist(emb[i+1], emb[i]) for i in range(len(emb)-1)])
if avg_diff < motion_threshold:
# 静态人脸 → 疑似照片攻击 → 拒绝签到
return "static_face"
else:
# 自然活体 → 允许签到
return "natural"
这个方案不需要额外模型参数,不需要额外传感器,完全基于已有的特征向量计算运动度量。实测照片攻击拦截率超过90%,视频回放拦截率达到80%。
当然也有误判——有次测试时一个同学故意保持静止不动,系统误判为“静态人脸”拒绝签到。这说明阈值参数还有优化空间,但方向是对的:用极低成本实现了基础级别的活体防御。
区块链存证:让考勤记录“钉”在链上
前端防住了代打卡,后端还需要解决数据可信问题。我们的方案是:基于Merkle树的区块链存证。
思路很简单:每次考勤产生一条记录(匿名ID + 时间戳 + 考勤状态),系统不是逐条上链(那样gas费太高),而是批量计算Merkle根,只把根哈希上链。
Merkle树的结构:
text
Merkle Root (上链)
/ \
Hash(1+2) Hash(3+4)
/ \ / \
Hash1 Hash2 Hash3 Hash4
| | | |
记录1 记录2 记录3 记录4
每一条考勤记录作为叶子节点,两两哈希向上汇聚,最终生成一个32字节的Merkle根。这个根值通过FISCO BCOS联盟链上链存证。
核心优势:
-
不可篡改:任何一条记录的改动都会导致Merkle根变化
-
高效验证:验证单条记录只需O(log n)次哈希运算
-
隐私友好:链上只存根哈希,不暴露任何具体记录
实测数据:单条记录上报约45ms,100条记录批量处理约312ms。家长端一键验真响应约85ms,月度批量验真不超过1秒。
家长端“一键验真”:让信任去中心化
区块链存证如果只有技术人员能验证,那就失去了意义。我们设计了一个家长端一键验真功能:
-
后端返回原始记录 + 默克尔证明路径 + 链上Merkle根
-
前端在浏览器本地独立完成哈希推导与比对
-
1秒内返回验证结果:“数据一致 ✓”或“数据已被篡改 ✗”
家长不需要懂区块链,不需要装任何插件,点一下按钮就能确认孩子的考勤记录是否真实。这个设计把验证能力下放给了每一位家长,而不是依赖学校或第三方平台来“背书”。
技术选型背后的考量
区块链方案我们调研过几个选项。最终选择FISCO BCOS主要基于三点:
-
国产开源:符合信创要求,社区活跃
-
联盟链而非公链:教育场景不需要完全匿名,联盟链的性能和合规性更合适
-
生态成熟:已有500余个标杆应用落地,技术文档完善
智能合约部署在FISCO BCOS 3.11.0上,通过Node.js后端与边缘端程序对接。边缘端只需HTTP上报考勤记录,后端负责Merkle树计算和链上交互——边缘端轻量化,复杂逻辑后移。
一点感悟
这个项目让我重新理解了“可信”的含义。传统系统的“可信”依赖管理员的人品、依赖平台的承诺。而区块链方案把“可信”变成了数学问题——哈希碰撞的概率低到可以忽略不计,篡改记录必然导致根值变化,这是密码学保证的,不需要信任任何第三方。
防代签解决的是数据来源的真实性,区块链解决的是数据存储的完整性。两者结合,才构成了一个完整的可信考勤闭环。