如何通过WinAPI(winscard.h)区分智能卡读卡器与生物识别设备
区分智能卡读卡器与Windows Hello生物识别设备的问题
问题背景
枚举计算机上读卡器的示例代码如下:
SCARDCONTEXT SCardContext; if (SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &SCardContext)) { char ReaderNames[1000]; DWORD Length = 1000; if(Status = SCardListReaders(SCardContext, NULL, ReaderNames, &Length)) { SCARD_READERSTATE ReaderStates[PCSC_READER_MAX_COUNT]; DWORD ReaderCount = 0; // Place the readers into the state array. LPSTR Rdr = ReaderNames; for (DWORD dwI = 0; dwI < MAXIMUM_SMARTCARD_READERS; dwI++ ) { if (0 == *Rdr) break; ReaderStates[dwI].szReader = Rdr; ReaderStates[dwI].dwCurrentState = SCARD_STATE_UNAWARE; Rdr += lstrlen(szRdr) + 1; } ReaderCount = dwI; // Do something with the readers; } SCardReleaseContext(SCardContext); }
实际使用中发现,Windows Hello指纹识别器会被上述代码识别为智能卡读卡器。调用SCardGetStatusChangeA()获取其状态时,返回值为0x422,对应SCARD_STATE_UNPOWERED | SCARD_STATE_PRESENT | SCARD_STATE_CHANGED。
需要解决两个核心问题:
- 如何区分真实智能卡读卡器与指纹、人脸识别设备?
- 为何指纹识别器会返回
SCARD_STATE_PRESENT状态?
解决方案与解释
一、区分真实读卡器与生物识别设备的方法
- 匹配设备名称关键词:Windows Hello生物识别设备的名称通常带有明显标识,比如包含“Windows Hello Fingerprint Reader”、“Face Recognition Device”等字符串,可通过字符串匹配直接过滤这类设备。
- 读取设备属性:调用
SCardGetAttrib函数获取读卡器的属性,比如SCARD_ATTR_VENDOR_NAME、SCARD_ATTR_DEVICE_SYSTEM_NAME。生物识别设备的厂商或系统属性会有别于常规智能卡读卡器,例如微软出品的设备会标注“Microsoft”相关字样,属性值不会符合普通读卡器的规格。 - 尝试智能卡专属操作:向设备发送标准智能卡指令(如获取ATR),生物识别设备无法响应这类指令,会返回错误码(如
SCARD_E_NO_SMARTCARD)。也可尝试调用SCardConnect连接设备,若无法正常建立连接且设备属于生物识别类型,即可排除其为真实智能卡读卡器。
二、指纹识别器返回SCARD_STATE_PRESENT的原因
Windows Hello指纹识别器是通过PC/SC框架模拟了智能卡读卡器的行为,目的是复用Windows的身份验证体系——生物识别验证流程部分借鉴了智能卡的认证逻辑,因此设备会向PC/SC服务报告“存在(PRESENT)”状态,让系统认为有类似智能卡的验证介质存在(实际这个“介质”是用户的指纹模板)。而SCARD_STATE_UNPOWERED状态则是因为这类设备不需要像智能卡那样供电,仅模拟了介质存在的状态。
内容的提问来源于stack exchange,提问作者Nikola
相关产品推荐
相关产品推荐

