12、Android 11 (API 30) 适配:一次性认证、认证白名单、隐私保护增强

Android 11 这次更新,说实话,对生物识别 API 的改动挺大的。我当年从 Android 10 迁移到 11 的时候,踩了不少坑。今天咱们就聊聊这三个核心点:一次性认证、认证白名单、还有隐私保护增强。

说白了,Google 在 Android 11 里把生物识别的安全模型重新梳理了一遍。以前有些模糊的地方,现在都明确了。你想想看,如果你的 App 还在用旧的方式,在 Android 11 设备上可能直接就崩了。

12.1 一次性认证(One-time Authentication)

什么叫一次性认证?就是用户验证一次指纹或虹膜,拿到一个短期有效的密钥,然后这个密钥只能用一次。用完就废了。

我有个项目是做移动支付的,用户每次付款都要重新刷脸。以前的做法是每次调用 authenticate(),但 Android 11 给了我们更优雅的方案。

核心变化: Android 11 引入了 BiometricPrompt.AuthenticationCallback 的新回调方法,明确区分了「一次性」和「持续性」认证。

来看代码:

// Android 11 推荐的一次性认证方式
BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
    .setTitle("验证身份")
    .setSubtitle("请扫描虹膜或指纹")
    .setAllowedAuthenticators(BIOMETRIC_STRONG | DEVICE_CREDENTIAL)
    .setConfirmationRequired(true)  // 关键:要求用户确认
    .build();

BiometricPrompt biometricPrompt = new BiometricPrompt(
    activity,
    executor,
    new BiometricPrompt.AuthenticationCallback() {
        @Override
        public void onAuthenticationSucceeded(
                @NonNull BiometricPrompt.AuthenticationResult result) {
            // 一次性认证成功
            // 注意:这个结果只能用一次
            CryptoObject cryptoObject = result.getCryptoObject();
            // 用 cryptoObject 做签名或加密
        }
    }
);

biometricPrompt.authenticate(promptInfo);

我的经验: 如果你设置了 setConfirmationRequired(true),用户必须主动确认(比如按一下按钮)才算认证成功。这在支付场景里特别重要,防止误触。

为什么会这样设计?因为有些场景下,你只想让用户验证一次,比如解锁一个加密文件。验证通过后,文件解密,密钥就失效了。下次再访问,还得重新验证。

12.2 认证白名单(Authentication Whitelist)

这个功能我特别喜欢。Android 11 允许你指定哪些生物识别方式可以用于认证。说白了,就是白名单机制。

以前你只能笼统地说「我要用生物识别」,但到底是虹膜、指纹还是人脸?你控制不了。现在你可以精确指定。

认证方式 常量值 说明
强生物识别 BIOMETRIC_STRONG 虹膜、指纹、人脸(Class 3)
弱生物识别 BIOMETRIC_WEAK 人脸(Class 2)
设备凭据 DEVICE_CREDENTIAL PIN、图案、密码

我建议你这样组合使用:

// 只允许虹膜或指纹(强生物识别),不允许人脸
int authenticators = BIOMETRIC_STRONG;

// 或者:强生物识别 + 设备密码作为备用
int authenticators = BIOMETRIC_STRONG | DEVICE_CREDENTIAL;

BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
    .setTitle("验证身份")
    .setAllowedAuthenticators(authenticators)
    .build();

注意: 如果你只设置了 BIOMETRIC_STRONG,但设备上没有虹膜或指纹传感器,那认证会直接失败。所以最好加上 DEVICE_CREDENTIAL 作为 fallback。

我曾经在一个项目里只用了 BIOMETRIC_STRONG,结果测试机是台只有人脸识别的平板,直接报错。嗯,从那以后我再也不敢不加 fallback 了。

12.3 隐私保护增强

Android 11 在隐私方面做了不少改进。对于生物识别来说,最明显的变化是:你无法再获取生物识别数据的 hash 或特征值了

以前有些开发者会偷偷拿指纹特征做设备指纹,现在这条路被堵死了。Google 明确说了:BiometricPrompt 只告诉你「认证成功」或「认证失败」,不给你任何生物特征数据。

来看一个典型的隐私保护场景:

// Android 11 之前(不推荐)
FingerprintManager fingerprintManager = 
    (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
// 这里可以获取到一些底层信息,但 Android 11 已经废弃了

// Android 11 推荐方式
BiometricPrompt biometricPrompt = new BiometricPrompt(
    activity,
    executor,
    new BiometricPrompt.AuthenticationCallback() {
        @Override
        public void onAuthenticationSucceeded(
                @NonNull BiometricPrompt.AuthenticationResult result) {
            // 你只能知道认证成功了
            // 无法获取任何生物特征数据
            // 这才是正确的隐私保护做法
        }
    }
);

隐私保护要点:

  • 认证结果不包含生物特征数据
  • 认证失败时不提供具体原因(是手指没放好还是虹膜没对准?不告诉你)
  • App 无法区分不同的生物特征(比如区分左眼和右眼)

你想想看,这样设计的好处是什么?就算你的 App 被逆向工程了,攻击者也拿不到用户的生物特征。因为你的 App 压根就没接触过这些数据。

12.4 知识体系总览

下面这张图是我整理的 Android 11 生物识别适配的核心逻辑,你看一眼就明白了:

Android 11 生物识别适配核心逻辑 一次性认证 • 认证结果仅用一次 • 需要 setConfirmationRequired • 适合支付/解锁场景 • CryptoObject 短期有效 • 用完即废,不可复用 认证白名单 • BIOMETRIC_STRONG • BIOMETRIC_WEAK • DEVICE_CREDENTIAL • 可自由组合 • 必须加 fallback 隐私保护增强 • 不返回生物特征数据 • 失败不提供具体原因 • 无法区分不同特征 • 废弃旧 API • 强制使用 BiometricPrompt 适配目标:安全、可控、隐私合规

你看,这三个模块其实是环环相扣的。一次性认证解决了「用一次还是用多次」的问题,白名单解决了「用什么方式认证」的问题,隐私保护解决了「数据安不安全」的问题。

我的建议: 如果你的 App 最低支持 Android 11,那就直接用 BiometricPrompt 的新 API,别再用旧的了。如果还要兼容 Android 10 及以下,记得做版本判断。

嗯,关于 Android 11 的适配,核心就是这些。实际项目中你可能会遇到各种奇怪的问题,比如某些国产手机对白名单的支持不完整。我的经验是:多测试,特别是不同厂商的设备,踩坑了再回来看看这篇文章,应该能帮你省不少时间。

公众号:蓝海资料掘金营,微信deep3321