执行两次PACE认证会引发错误吗?JMRTD库eID读取异常求助
解决JMRTD库连续调用doPace()出现0x6986错误的方案
这个错误是电子身份证(eID)的安全机制导致的:卡片执行PACE协议后会启动会话冷却/锁定机制,短时间内重复发起PACE握手会被拒绝(SW=0x6986),即使断开读卡器连接,卡片的会话状态也不会自动重置,必须等待冷却期结束或主动触发重置。以下是具体解决办法:
1. 主动重置卡片会话,终止锁定
每次完成数据读取后,必须主动调用重置命令,而不是仅断开读卡器连接。通过以下步骤确保卡片会话被重置:
- 调用
PassportService的close()方法释放资源 - 调用
Card对象的disconnect(true)方法,注意参数必须为true,该参数会向卡片发送重置指令,直接解除会话锁定
示例代码:
PassportService passportService = null; Card card = null; try { // 初始化读卡器、卡片、PassportService逻辑 passportService.doPace(...); // 执行数据读取操作 } finally { // 释放PassportService资源 if (passportService != null) { try { passportService.close(); } catch (IOException e) { // 处理异常 } } // 重置卡片,解除会话锁定 if (card != null) { try { card.disconnect(true); } catch (CardException e) { // 处理异常 } } }
2. 复用已建立的PACE会话
如果业务需要连续操作卡片,不要重复调用doPace()。第一次doPace()成功后,保持PassportService实例的有效性,后续直接使用该实例读取数据即可,无需重新执行PACE握手。
3. 测试场景下的延迟重试逻辑
如果是测试场景必须重复发起PACE握手,可以捕获CardException并检查错误码,当遇到0x6986时,添加延迟重试机制,延迟时间建议设置为65秒以上(略长于卡片默认的1分钟冷却期)。
示例代码:
int maxRetries = 3; long delayMillis = 65000; // 65秒延迟 boolean success = false; while (maxRetries > 0 && !success) { try { passportService.doPace(...); success = true; } catch (CardException e) { if (e.getMessage().contains("0x6986") && maxRetries > 1) { try { Thread.sleep(delayMillis); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); throw new RuntimeException("重试被中断", ie); } maxRetries--; } else { throw e; } } }
内容的提问来源于stack exchange,提问作者Desperado
相关产品推荐
相关产品推荐

