人脸识别一度被视为公共场所身份核验的最优解:不用带卡、不用记密码,看一眼就能通行。但生物特征信息的特殊性在于它一旦泄露便终身无法更改,密码可以重置,脸却换不了。正因如此,全球立法者开始对公共场所的人脸识别应用施加越来越严格的限制,专门性规定已经落地,执法案例也陆续出现。对开发者和企业来说,读懂这些法律红线,并掌握不依赖人脸识别的替代技术方案,已经成为智能化项目立项阶段就必须完成的功课。

一、法律进展:从原则条款到专门规定的演进
国内对人脸识别的规制经历了从分散到集中的过程。2021年施行的《个人信息保护法》将人脸信息明确列为敏感个人信息,其第二十六条规定,在公共场所安装图像采集、个人身份识别设备,应当为维护公共安全所必需,遵守国家有关规定,并设置显著的提示标识;所收集的图像与身份识别信息只能用于维护公共安全的目的。同年,最高人民法院出台了审理人脸识别相关民事案件的司法解释,明确物业服务企业不得将人脸识别作为进出小区的唯一验证方式,业主有权拒绝刷脸并要求提供其他合理通道。
真正让规则变得可执行的,是随后由网信部门联合公安部门公布的《人脸识别技术应用安全管理办法》。这份专门规定把此前散落各处的要求整合成了操作细则:在公共场所安装人脸识别设备应当以维护公共安全为目的,并依法履行备案程序;宾馆客房、公共浴室、公共卫生间、公共更衣室等私密空间一律禁止安装;处理人脸信息必须取得个人的单独同意,法律另有规定的除外;存储期限遵循最小必要原则,目的实现后应当及时删除;所收集的人脸信息只能用于标识特定身份,不得开展与身份识别无关的分析活动,例如推测种族、民族、宗教信仰、健康状况等。
国际层面的趋势同样明确。欧盟《人工智能法案》把在公共场所为执法目的使用实时远程生物识别列为原则上禁止的高风险实践,只保留了极窄的例外空间;美国伊利诺伊州的生物特征信息隐私法对未经书面同意收集生物特征数据的行为设定了按人次计算的赔偿标准,多年来催生了大量集体诉讼。这些规定共同传递了一个信号:人脸识别不再是随便一个摄像头加一套算法就能上线的普通功能,而是一项需要严格论证必要性的高敏感度处理活动。
二、红线在哪里:公共场所部署的四类典型违规场景
第一类是唯一验证方式问题。不少小区、商场、写字楼的门禁系统在升级时只保留了刷脸通道,撤掉了刷卡和扫码选项,用户要么交出人脸信息、要么无法通行。这种捆绑式采集直接违反了不得将人脸识别作为唯一身份验证方式的要求,也是目前投诉和诉讼中最常见的情形。合规的做法是至少保留一种非生物特征验证通道,并且这条通道的体验不能被刻意劣化。
第二类是私密场所安装。任何在宾馆客房、公共浴室、公共卫生间、公共更衣室内部署图像采集或人脸识别设备的行为都触碰了禁止性红线,没有例外论证空间。容易踩坑的是一些智能楼宇项目,把带人脸识别功能的摄像头装在通往更衣室的走廊尽头,虽然不在更衣室内部,但视野覆盖了出入口,这类部署同样存在被认定为侵害隐私的风险,需要在方案设计阶段就通过物理遮挡或调整安装角度来规避。
第三类是功能越界。以客流统计、安防监控名义安装的摄像头,如果在后台悄悄运行人脸识别算法,把匿名化的客流数据变成了可追踪个人行踪的轨迹数据,性质就完全变了。判断标准在于是否对人脸进行了特征提取并关联到特定身份,一旦关联,就必须满足单独同意、目的限定等全部合规义务。
第四类是数据管理失责。原始人脸图像明文存储在本地硬盘、特征库长期不清理、人脸数据被共享给第三方营销系统,这些做法即便采集环节合法,也会在存储与使用环节构成违法。从已公布的处罚案例看,相当比例的问题出在数据生命周期管理上,而不是摄像头本身。
三、合规替代方案:不用人脸识别也能完成身份核验
对绝大多数通行、签到、会员核验场景来说,人脸识别并非不可替代。一次性二维码加动态令牌是目前落地成本最低的方案:访客在预约时由系统签发带签名的限时令牌,到场扫码验证,令牌用后即焚,天然满足最小必要原则。下面是一个用Python实现的门禁令牌服务,采用HMAC签名防止伪造,配合已用令牌集合防止重放攻击。
import hmac
import hashlib
import time
class GateTokenService:
"""基于HMAC签名的一次性通行令牌服务"""
def __init__(self, secret_key):
self.secret_key = secret_key.encode()
# 已使用令牌集合,防止重放攻击
self.used_tokens = set()
def issue_token(self, visitor_id, valid_seconds=300):
"""签发绑定访客身份的限时令牌"""
expire_at = int(time.time()) + valid_seconds
raw = visitor_id + ":" + str(expire_at)
signature = hmac.new(self.secret_key, raw.encode(), hashlib.sha256).hexdigest()
return raw + ":" + signature
def verify_token(self, token):
"""验证令牌:校验签名与有效期,并保证只可用一次"""
if token in self.used_tokens:
return False, "令牌已被使用"
parts = token.split(":")
if len(parts) != 3:
return False, "令牌格式错误"
visitor_id, expire_at, signature = parts
raw = visitor_id + ":" + expire_at
expected = hmac.new(self.secret_key, raw.encode(), hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, signature):
return False, "签名校验失败"
if int(expire_at) < int(time.time()):
return False, "令牌已过期"
self.used_tokens.add(token)
return True, "访客 " + visitor_id + " 验证通过"
# 演示:预约系统签发令牌,门禁端验证
service = GateTokenService("server-side-secret-key")
token = service.issue_token("visitor-2046")
print(service.verify_token(token)) # 第一次验证通过
print(service.verify_token(token)) # 第二次触发重放防护这套方案的关键设计有三点:令牌绑定访客身份与过期时间,签名密钥只保存在服务端;验证通过后立即作废,即使二维码被拍照转发也无法二次使用;全程不涉及任何生物特征数据,个人信息收集范围被压缩到访客编号和进出记录。对于员工门禁,可以把二维码换成手机虚拟卡或NFC实体卡,验证逻辑完全复用。
另一个思路是设备端去标识化。很多场景其实只需要知道有没有人,并不需要知道这个人是谁。比如自动感应门、客流计数器、智能广告屏的唤醒逻辑,用人体感应或人脸检测就够了,不需要特征提取和比对。下面的代码演示了如何用OpenCV只做人脸检测并返回布尔结果,图像帧处理完立即丢弃,不落盘、不提取特征。
import cv2
def detect_presence_only(frame):
"""只判断画面中是否出现人脸,不提取特征、不落盘"""
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cascade = cv2.CascadeClassifier(
cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
)
faces = cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5)
# 仅返回布尔结果,原始图像帧用完即弃
return len(faces) > 0
def on_frame_arrived(frame):
"""门禁联动:有人靠近时唤醒扫码界面,而非刷脸识别"""
if detect_presence_only(frame):
print("检测到人员靠近,激活二维码扫码界面")
else:
print("区域内无人,设备进入低功耗待机")检测与识别的区分在合规上意义重大:检测只是判断画面中是否存在人脸这一通用对象,不产生个人身份信息;识别则是对特定自然人的生物特征进行采集和比对,会触发敏感个人信息处理义务。把需求拆解到这一层,很多项目会发现真正需要人脸识别的环节比想象中少得多。
四、必须保留人脸识别时的合规改造
确实存在难以替代的场景,比如交通枢纽的人证比对、金融机构高风险业务核身。这类应用要围绕最小化原则做技术改造。首先是存储改造:不保存原始人脸图像,只保存加密后的特征向量,且加密密钥与数据库分离管理。下面是用AES-GCM对特征向量做加密存储的示例。
import os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
def encrypt_feature_vector(feature_bytes, key):
"""对人脸特征向量做AES-GCM加密,替代明文存储"""
aesgcm = AESGCM(key)
# 每次加密使用随机nonce,同一密钥下绝不重复
nonce = os.urandom(12)
ciphertext = aesgcm.encrypt(nonce, feature_bytes, None)
return nonce, ciphertext
def decrypt_feature_vector(nonce, ciphertext, key):
"""核验时解密特征用于本地比对,比对结束即释放"""
aesgcm = AESGCM(key)
return aesgcm.decrypt(nonce, ciphertext, None)
# 注册环节:只保存加密特征,不保存原始人脸图像
key = AESGCM.generate_key(bit_length=256)
feature = os.urandom(512) # 模拟512维特征向量序列化后的字节串
nonce, ciphertext = encrypt_feature_vector(feature, key)
print("加密后密文长度:", len(ciphertext))
# 核验环节:解密后与现场提取的特征比对
restored = decrypt_feature_vector(nonce, ciphertext, key)
print("解密结果与原文一致:", restored == feature)其次是期限与用途控制:特征库设置自动过期策略,比对完成后即用即删;对特征库的每一次访问都落审计日志,任何批量导出行为触发告警。再次是交互合规:设备旁设置显著的提示标识,界面上提供明确的拒绝选项,用户选择拒绝后系统自动切换到人工核验或证件加密码的替代流程,而不是把用户晾在原地。
在架构层面,优先选择端侧计算方案。特征提取在设备本地完成,只把比对结果或脱敏后的统计指标回传服务器,原始图像和特征向量不出设备,能显著降低集中式泄露的风险。对于必须集中比对的场景,可以考虑将特征库分片存储在不同密钥体系之下,单点失陷不至于拖垮整个库。
五、落地建议:从评估到审计的完整流程
项目立项阶段先做个人信息保护影响评估,即PIA,回答三个问题:业务目的是什么、为什么必须用人脸识别、有没有对个人权益影响更小的替代方案。这份评估文档既是内部决策依据,也是监管检查时的必要材料。实践中不少团队在这一步就会发现二维码或刷卡方案已经够用,人脸识别纯属为了显得智能而堆砌的功能。
确定要用人脸识别后,把合规要求翻译成技术需求清单:备案流程走完了吗、单独同意的交互流程设计好了吗、替代验证通道的可用性达标了吗、存储加密和自动删除策略上线了吗、审计日志是否覆盖所有敏感操作。逐项验收,而不是等上线后再补课。
最后是持续运营。法规在更新,执法口径也在细化,建议每半年复核一次人脸数据的存量与使用情况,清理超出保存期限的数据,复查第三方合作方的数据处理行为。合规不是一次性的上线动作,而是贯穿数据全生命周期的常态工作。把这套流程跑顺,人脸识别这类高敏感度功能才能在法律框架内长期稳定地运转下去。