HarmonyOS APP开发中的生物识别小实践

举报
Jack20 发表于 2026/06/20 18:32:34 2026/06/20
【摘要】 HarmonyOS APP开发中的生物识别:@ohos.userIAM.userAuth 深度解析📌 核心要点:生物识别是 HarmonyOS 安全认证的最高体验层,掌握 userAuth 模块才能实现指纹/人脸认证与安全级别的精准匹配 一、背景与动机想象一下这个场景——你在地铁上单手拿着手机,另一只手提着早餐,这时候需要打开支付 App 确认一笔订单。如果还要输入6位密码,那体验简直灾...

HarmonyOS APP开发中的生物识别:@ohos.userIAM.userAuth 深度解析

📌 核心要点:生物识别是 HarmonyOS 安全认证的最高体验层,掌握 userAuth 模块才能实现指纹/人脸认证与安全级别的精准匹配


一、背景与动机

想象一下这个场景——你在地铁上单手拿着手机,另一只手提着早餐,这时候需要打开支付 App 确认一笔订单。如果还要输入6位密码,那体验简直灾难。但如果只需要看一眼手机,或者轻轻碰一下指纹传感器,支付就完成了——这就是生物识别的魅力。

生物识别不是什么新鲜事,但在 HarmonyOS 上实现它有很多讲究。不同的场景需要不同的认证方式:支付需要高安全级别的人脸+指纹双重认证,解锁App只需要低安全级别的面部识别就够了。如果一刀切地使用最高安全级别,用户体验会很差;如果安全级别太低,又可能被照片或假指纹骗过。

HarmonyOS 的 @ohos.userIAM.userAuth 模块提供了灵活的生物识别认证框架,支持指纹、人脸、PIN 码等多种认证方式,并且可以按需配置安全等级。理解这个模块,你就能在安全性和便利性之间找到最佳平衡点。


二、核心原理

2.1 生物识别认证架构

flowchart TB
    A[应用发起认证请求] --> B[UserAuthClient]
    B --> C{认证方式选择}
    C -->|指纹| D[FingerprintAuth]
    C -->|人脸| E[FaceAuth]
    C -->|PIN| F[PinAuth]
    C -->|组合| G[MultiFactorAuth]

    D --> H[TEE安全环境]
    E --> H
    F --> H
    G --> H

    H --> I{安全级别判断}
    I -->|S1| J[便捷级<br/>照片可能通过]
    I -->|S2| K[安全级<br/>需要活体检测]
    I -->|S3| L[高安全级<br/>硬件级防伪]

    J --> M[返回认证结果]
    K --> M
    L --> M

    classDef primary fill:#4CAF50,stroke:#388E3C,color:#fff
    classDef warning fill:#FF9800,stroke:#F57C00,color:#fff
    classDef error fill:#F44336,stroke:#D32F2F,color:#fff
    classDef info fill:#2196F3,stroke:#1976D2,color:#fff
    classDef purple fill:#9C27B0,stroke:#7B1FA2,color:#fff

    class A,B primary
    class C,D,E,F,G info
    class H purple
    class I,J,K,L warning
    class M primary

2.2 认证方式与安全级别

HarmonyOS 定义了三种生物识别类型和三个安全级别,它们之间的组合决定了认证的严格程度:

认证类型 API常量 说明 硬件要求
PIN码 PIN 数字/图案密码 无特殊要求
指纹 FINGERPRINT 指纹传感器采集 指纹传感器
人脸 FACE 前置摄像头采集 前置摄像头+3D结构光(S3级别)
安全级别 API常量 说明 典型场景
S1 S1 便捷级,可能被伪造 App解锁
S2 S2 安全级,需要活体检测 普通支付
S3 S3 高安全级,硬件级防伪 大额转账

2.3 认证流程

sequenceDiagram
    participant App as 应用
    participant UserAuth as UserAuth服务
    participant TEE as TEE安全环境
    participant User as 用户

    App->>UserAuth: 1. 创建认证会话(authIntent)
    UserAuth->>UserAuth: 2. 检查认证能力可用性
    UserAuth->>App: 3. 返回可用认证方式
    App->>UserAuth: 4. 发起认证(onStart)
    UserAuth->>TEE: 5. 启动TEE内认证
    TEE->>User: 6. 提示用户操作(放手指/看镜头)
    User->>TEE: 7. 提供生物特征
    TEE->>TEE: 8. 特征比对(TEE内完成)
    TEE->>UserAuth: 9. 返回认证结果
    UserAuth->>App: 10. 回调通知认证结果

    Note over TEE: 生物特征数据永不离开TEE<br/>应用只能获得成功/失败结果

关键点:生物特征数据(指纹图像、人脸数据)永远不会离开 TEE 安全环境。应用只能获得"认证成功"或"认证失败"的结果,无法获取原始生物特征数据。这就像你把钥匙交给保险箱验证——保险箱只告诉你"钥匙对不对",不会把锁芯结构暴露给你。


三、代码实战

3.1 基础生物识别认证

最简单的用法——检测设备是否支持生物识别,然后发起一次认证。

import { userAuth } from '@kit.UserAuthenticationKit';
import { BusinessError } from '@kit.BasicServicesKit';

/**
 * 生物识别认证管理器
 * 封装常用的生物识别认证操作
 */
class BiometricAuthManager {
  private authInstance: userAuth.UserAuthInstance | null = null;

  /**
   * 检查设备是否支持指定的认证方式
   * @param authType 认证类型
   * @param trustLevel 信任级别
   */
  async checkAuthAbility(
    authType: userAuth.UserAuthType = userAuth.UserAuthType.FINGERPRINT,
    trustLevel: userAuth.AuthTrustLevel = userAuth.AuthTrustLevel.ATL2
  ): Promise<boolean> {
    try {
      // 查询认证能力
      const result = userAuth.getAvailableStatus(authType, trustLevel);

      if (result === userAuth.UserAuthResult.SUCCESS) {
        console.info(`[BiometricAuth] 设备支持 ${this.getAuthTypeName(authType)} ` +
          `认证,安全级别 ${this.getTrustLevelName(trustLevel)}`);
        return true;
      } else {
        console.warn(`[BiometricAuth] 设备不支持该认证配置: result=${result}`);
        return false;
      }
    } catch (error) {
      const err = error as BusinessError;
      console.error(`[BiometricAuth] 检查认证能力失败: code=${err.code}, msg=${err.message}`);

      // 常见错误码处理
      switch (err.code) {
        case 12500001: // 认证能力不可用
          console.error('[BiometricAuth] 该认证方式不可用,请检查设备硬件');
          break;
        case 12500002: // 用户未录入生物特征
          console.error('[BiometricAuth] 用户尚未录入指纹/人脸,请先到系统设置中录入');
          break;
        case 12500003: // 认证被锁定
          console.error('[BiometricAuth] 认证次数过多被锁定,请稍后重试');
          break;
      }
      return false;
    }
  }

  /**
   * 发起生物识别认证
   * @param authType 认证类型
   * @param trustLevel 信任级别
   * @param title 认证对话框标题
   * @param subtitle 认证对话框副标题
   */
  async authenticate(
    authType: userAuth.UserAuthType = userAuth.UserAuthType.FINGERPRINT,
    trustLevel: userAuth.AuthTrustLevel = userAuth.AuthTrustLevel.ATL2,
    title: string = '请验证身份',
    subtitle: string = '使用指纹验证'
  ): Promise<userAuth.UserAuthResult> {
    try {
      // 1. 先检查认证能力
      const available = await this.checkAuthAbility(authType, trustLevel);
      if (!available) {
        console.error('[BiometricAuth] 认证能力不可用,无法发起认证');
        return userAuth.UserAuthResult.GENERAL_ERROR;
      }

      // 2. 创建认证请求
      const authRequest: userAuth.UserAuthRequest = {
        challenge: this.generateChallenge(),  // 挑战码,防止重放攻击
        authType: authType,
        trustLevel: trustLevel,
      };

      // 3. 创建认证实例
      this.authInstance = userAuth.getUserAuthInstance(authRequest);

      // 4. 订阅认证结果
      return new Promise<userAuth.UserAuthResult>((resolve, reject) => {
        this.authInstance!.on('result', {
          onResult(result: userAuth.UserAuthResult, extraInfo?: userAuth.AuthResultInfo) {
            console.info(`[BiometricAuth] 认证结果: ${result}`);

            if (result === userAuth.UserAuthResult.SUCCESS) {
              console.info('[BiometricAuth] 认证成功!');
              if (extraInfo) {
                console.info(`[BiometricAuth] 认证方式: ${extraInfo.authType}`);
                console.info(`[BiometricAuth] 安全级别: ${extraInfo.trustLevel}`);
              }
            } else if (result === userAuth.UserAuthResult.FAIL) {
              console.warn('[BiometricAuth] 认证失败,生物特征不匹配');
            } else if (result === userAuth.UserAuthResult.CANCELED) {
              console.info('[BiometricAuth] 用户取消了认证');
            } else if (result === userAuth.UserAuthResult.TIMEOUT) {
              console.warn('[BiometricAuth] 认证超时');
            }

            resolve(result);
          }
        });

        // 5. 启动认证
        this.authInstance!.start();
        console.info('[BiometricAuth] 认证已启动');
      });
    } catch (error) {
      const err = error as BusinessError;
      console.error(`[BiometricAuth] 认证异常: code=${err.code}, msg=${err.message}`);
      return userAuth.UserAuthResult.GENERAL_ERROR;
    }
  }

  /**
   * 取消正在进行的认证
   */
  cancelAuthentication(): void {
    if (this.authInstance) {
      try {
        this.authInstance.cancel();
        console.info('[BiometricAuth] 认证已取消');
      } catch (error) {
        const err = error as BusinessError;
        console.error(`[BiometricAuth] 取消认证失败: ${err.message}`);
      }
    }
  }

  /**
   * 生成随机挑战码
   * 用于防止重放攻击
   */
  private generateChallenge(): string {
    const length = 16;
    const array = new Uint8Array(length);
    for (let i = 0; i < length; i++) {
      array[i] = Math.floor(Math.random() * 256);
    }
    return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
  }

  /**
   * 获取认证类型名称
   */
  private getAuthTypeName(type: userAuth.UserAuthType): string {
    switch (type) {
      case userAuth.UserAuthType.PIN: return 'PIN码';
      case userAuth.UserAuthType.FINGERPRINT: return '指纹';
      case userAuth.UserAuthType.FACE: return '人脸';
      default: return '未知';
    }
  }

  /**
   * 获取信任级别名称
   */
  private getTrustLevelName(level: userAuth.AuthTrustLevel): string {
    switch (level) {
      case userAuth.AuthTrustLevel.ATL1: return 'S1(便捷级)';
      case userAuth.AuthTrustLevel.ATL2: return 'S2(安全级)';
      case userAuth.AuthTrustLevel.ATL3: return 'S3(高安全级)';
      case userAuth.AuthTrustLevel.ATL4: return 'S4(最高安全级)';
      default: return '未知';
    }
  }
}

// 使用示例:App解锁场景
async function demoAppUnlock() {
  const authManager = new BiometricAuthManager();

  // 使用指纹进行App解锁(S2安全级别)
  const result = await authManager.authenticate(
    userAuth.UserAuthType.FINGERPRINT,
    userAuth.AuthTrustLevel.ATL2,
    '解锁应用',
    '请使用指纹验证身份'
  );

  if (result === userAuth.UserAuthResult.SUCCESS) {
    console.info('[Demo] 应用解锁成功');
    // 进入应用主界面
  } else {
    console.warn('[Demo] 应用解锁失败,回退到密码输入');
    // 显示密码输入界面
  }
}

3.2 多因素组合认证

高安全场景(如支付、转账)需要多种认证方式组合使用,提高安全性。

import { userAuth } from '@kit.UserAuthenticationKit';
import { BusinessError } from '@kit.BasicServicesKit';

/**
 * 多因素认证管理器
 * 支持指纹+人脸、PIN+指纹等组合认证
 */
class MultiFactorAuthManager {
  /**
   * 认证配置:定义不同场景的认证策略
   */
  private readonly AUTH_POLICIES: Map<string, AuthPolicy> = new Map([
    ['app_unlock', {
      description: '应用解锁',
      primaryAuth: userAuth.UserAuthType.FACE,
      fallbackAuth: userAuth.UserAuthType.FINGERPRINT,
      trustLevel: userAuth.AuthTrustLevel.ATL1,
      requireMultiFactor: false,
    }],
    ['payment', {
      description: '支付验证',
      primaryAuth: userAuth.UserAuthType.FINGERPRINT,
      fallbackAuth: userAuth.UserAuthType.PIN,
      trustLevel: userAuth.AuthTrustLevel.ATL2,
      requireMultiFactor: false,
    }],
    ['large_transfer', {
      description: '大额转账',
      primaryAuth: userAuth.UserAuthType.FINGERPRINT,
      fallbackAuth: userAuth.UserAuthType.FACE,
      trustLevel: userAuth.AuthTrustLevel.ATL3,
      requireMultiFactor: true,  // 需要双重认证
    }],
    ['sensitive_operation', {
      description: '敏感操作',
      primaryAuth: userAuth.UserAuthType.FACE,
      fallbackAuth: userAuth.UserAuthType.PIN,
      trustLevel: userAuth.AuthTrustLevel.ATL3,
      requireMultiFactor: true,
    }],
  ]);

  /**
   * 根据场景执行认证
   * @param scenario 认证场景
   */
  async authenticateByScenario(scenario: string): Promise<boolean> {
    const policy = this.AUTH_POLICIES.get(scenario);
    if (!policy) {
      console.error(`[MultiFactor] 未知场景: ${scenario}`);
      return false;
    }

    console.info(`[MultiFactor] 场景: ${policy.description}`);

    // 尝试主要认证方式
    const primaryResult = await this.tryAuthenticate(
      policy.primaryAuth,
      policy.trustLevel
    );

    if (primaryResult === userAuth.UserAuthResult.SUCCESS) {
      // 如果不需要多因素认证,直接返回成功
      if (!policy.requireMultiFactor) {
        return true;
      }

      // 需要多因素认证,继续第二因素
      console.info('[MultiFactor] 第一因素认证成功,继续第二因素...');
      const secondaryResult = await this.tryAuthenticate(
        policy.fallbackAuth,
        policy.trustLevel
      );

      return secondaryResult === userAuth.UserAuthResult.SUCCESS;
    }

    // 主要认证方式失败或不可用,尝试回退方式
    if (primaryResult === userAuth.UserAuthResult.CANCELED) {
      // 用户主动取消,不再尝试回退
      return false;
    }

    console.info('[MultiFactor] 主要认证方式不可用,尝试回退方式...');
    const fallbackResult = await this.tryAuthenticate(
      policy.fallbackAuth,
      policy.trustLevel
    );

    if (fallbackResult === userAuth.UserAuthResult.SUCCESS) {
      if (!policy.requireMultiFactor) {
        return true;
      }

      // 多因素场景:回退方式成功后,还需要另一种认证
      console.info('[MultiFactor] 回退方式认证成功,继续补充认证...');
      const supplementResult = await this.tryAuthenticate(
        policy.primaryAuth,
        policy.trustLevel
      );
      return supplementResult === userAuth.UserAuthResult.SUCCESS;
    }

    return false;
  }

  /**
   * 尝试使用指定方式进行认证
   */
  private async tryAuthenticate(
    authType: userAuth.UserAuthType,
    trustLevel: userAuth.AuthTrustLevel
  ): Promise<userAuth.UserAuthResult> {
    try {
      // 先检查可用性
      const availableStatus = userAuth.getAvailableStatus(authType, trustLevel);
      if (availableStatus !== userAuth.UserAuthResult.SUCCESS) {
        console.warn(`[MultiFactor] ${this.getAuthTypeName(authType)} 不可用`);
        return userAuth.UserAuthResult.GENERAL_ERROR;
      }

      // 创建认证请求
      const authRequest: userAuth.UserAuthRequest = {
        challenge: this.generateChallenge(),
        authType: authType,
        trustLevel: trustLevel,
      };

      const authInstance = userAuth.getUserAuthInstance(authRequest);

      return new Promise<userAuth.UserAuthResult>((resolve) => {
        authInstance.on('result', {
          onResult(result: userAuth.UserAuthResult) {
            resolve(result);
          }
        });

        authInstance.start();
      });
    } catch (error) {
      const err = error as BusinessError;
      console.error(`[MultiFactor] 认证异常: ${err.message}`);
      return userAuth.UserAuthResult.GENERAL_ERROR;
    }
  }

  private generateChallenge(): string {
    const length = 16;
    const array = new Uint8Array(length);
    for (let i = 0; i < length; i++) {
      array[i] = Math.floor(Math.random() * 256);
    }
    return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
  }

  private getAuthTypeName(type: userAuth.UserAuthType): string {
    switch (type) {
      case userAuth.UserAuthType.PIN: return 'PIN码';
      case userAuth.UserAuthType.FINGERPRINT: return '指纹';
      case userAuth.UserAuthType.FACE: return '人脸';
      default: return '未知';
    }
  }
}

/**
 * 认证策略接口
 */
interface AuthPolicy {
  description: string;
  primaryAuth: userAuth.UserAuthType;
  fallbackAuth: userAuth.UserAuthType;
  trustLevel: userAuth.AuthTrustLevel;
  requireMultiFactor: boolean;
}

// 使用示例:不同场景的认证策略
async function demoMultiFactorAuth() {
  const manager = new MultiFactorAuthManager();

  // 场景1:应用解锁(低安全级别,单因素)
  const unlockResult = await manager.authenticateByScenario('app_unlock');
  console.info(`[Demo] 应用解锁: ${unlockResult ? '成功' : '失败'}`);

  // 场景2:支付验证(中安全级别,单因素+回退)
  const paymentResult = await manager.authenticateByScenario('payment');
  console.info(`[Demo] 支付验证: ${paymentResult ? '成功' : '失败'}`);

  // 场景3:大额转账(高安全级别,双重认证)
  const transferResult = await manager.authenticateByScenario('large_transfer');
  console.info(`[Demo] 大额转账: ${transferResult ? '成功' : '失败'}`);
}

3.3 认证状态监听与安全等级配置

在实际应用中,我们需要监听认证状态变化,并根据不同的安全等级动态调整认证策略。

import { userAuth } from '@kit.UserAuthenticationKit';
import { BusinessError } from '@kit.BasicServicesKit';

/**
 * 认证状态监听器
 * 监听生物特征变化和认证状态
 */
class AuthStateMonitor {
  private authInstance: userAuth.UserAuthInstance | null = null;

  /**
   * 查询设备支持的所有认证能力
   * 返回每种认证方式的可用状态
   */
  async queryDeviceAuthCapabilities(): Promise<AuthCapability[]> {
    const capabilities: AuthCapability[] = [];
    const authTypes = [
      userAuth.UserAuthType.PIN,
      userAuth.UserAuthType.FINGERPRINT,
      userAuth.UserAuthType.FACE,
    ];
    const trustLevels = [
      userAuth.AuthTrustLevel.ATL1,
      userAuth.AuthTrustLevel.ATL2,
      userAuth.AuthTrustLevel.ATL3,
      userAuth.AuthTrustLevel.ATL4,
    ];

    for (const authType of authTypes) {
      for (const trustLevel of trustLevels) {
        try {
          const status = userAuth.getAvailableStatus(authType, trustLevel);
          const isAvailable = status === userAuth.UserAuthResult.SUCCESS;

          capabilities.push({
            authType: authType,
            trustLevel: trustLevel,
            isAvailable: isAvailable,
            authTypeName: this.getAuthTypeName(authType),
            trustLevelName: this.getTrustLevelName(trustLevel),
          });

          if (isAvailable) {
            console.info(`[AuthState] ✅ ${this.getAuthTypeName(authType)} ` +
              `@ ${this.getTrustLevelName(trustLevel)} 可用`);
          }
        } catch {
          // 该组合不支持,跳过
        }
      }
    }

    console.info(`[AuthState] 设备共有 ${capabilities.filter(c => c.isAvailable).length} 种可用认证组合`);
    return capabilities;
  }

  /**
   * 根据安全需求推荐最佳认证方案
   * @param securityRequirement 安全需求等级
   */
  async recommendAuthScheme(
    securityRequirement: 'low' | 'medium' | 'high' | 'critical'
  ): Promise<RecommendedScheme> {
    const capabilities = await this.queryDeviceAuthCapabilities();

    // 根据安全需求确定最低信任级别
    const minTrustLevel: Map<string, userAuth.AuthTrustLevel> = new Map([
      ['low', userAuth.AuthTrustLevel.ATL1],
      ['medium', userAuth.AuthTrustLevel.ATL2],
      ['high', userAuth.AuthTrustLevel.ATL3],
      ['critical', userAuth.AuthTrustLevel.ATL4],
    ]);

    const requiredLevel = minTrustLevel.get(securityRequirement) ?? userAuth.AuthTrustLevel.ATL2;

    // 优先选择指纹(便捷性最好),其次人脸,最后PIN
    const authPriority = [
      userAuth.UserAuthType.FINGERPRINT,
      userAuth.UserAuthType.FACE,
      userAuth.UserAuthType.PIN,
    ];

    let recommended: AuthCapability | null = null;
    for (const authType of authPriority) {
      const found = capabilities.find(
        c => c.authType === authType && c.trustLevel === requiredLevel && c.isAvailable
      );
      if (found) {
        recommended = found;
        break;
      }
    }

    // 如果精确匹配失败,降低信任级别再找
    if (!recommended) {
      for (const authType of authPriority) {
        const found = capabilities.find(
          c => c.authType === authType && c.isAvailable
        );
        if (found) {
          recommended = found;
          console.warn(`[AuthState] 无法满足${securityRequirement}安全需求,降级为 ${found.trustLevelName}`);
          break;
        }
      }
    }

    const scheme: RecommendedScheme = {
      securityRequirement: securityRequirement,
      primaryAuth: recommended?.authType ?? userAuth.UserAuthType.PIN,
      trustLevel: recommended?.trustLevel ?? userAuth.AuthTrustLevel.ATL1,
      isDowngraded: recommended?.trustLevel !== requiredLevel,
      description: recommended
        ? `推荐使用${recommended.authTypeName}${recommended.trustLevelName}`
        : '无可用的生物识别方式,请使用PIN码',
    };

    console.info(`[AuthState] 推荐方案: ${scheme.description}`);
    return scheme;
  }

  /**
   * 执行带完整回调的认证
   * 监听认证过程中的各种状态变化
   */
  async authenticateWithFullCallbacks(
    authType: userAuth.UserAuthType,
    trustLevel: userAuth.AuthTrustLevel
  ): Promise<userAuth.UserAuthResult> {
    try {
      const authRequest: userAuth.UserAuthRequest = {
        challenge: this.generateChallenge(),
        authType: authType,
        trustLevel: trustLevel,
      };

      this.authInstance = userAuth.getUserAuthInstance(authRequest);

      return new Promise<userAuth.UserAuthResult>((resolve) => {
        // 监听认证结果
        this.authInstance!.on('result', {
          onResult(result: userAuth.UserAuthResult, extraInfo?: userAuth.AuthResultInfo) {
            console.info(`[AuthCallback] 认证结果: ${result}`);
            if (extraInfo) {
              console.info(`[AuthCallback] 错误码: ${extraInfo.errCode ?? '无'}`);
              console.info(`[AuthCallback] 认证耗时: ${extraInfo.remainTimes ?? '未知'}`);
            }
            resolve(result);
          }
        });

        // 启动认证
        this.authInstance!.start();
        console.info('[AuthCallback] 认证已启动,等待用户操作...');
      });
    } catch (error) {
      const err = error as BusinessError;
      console.error(`[AuthCallback] 认证异常: ${err.message}`);
      return userAuth.UserAuthResult.GENERAL_ERROR;
    }
  }

  /**
   * 释放认证资源
   */
  release(): void {
    if (this.authInstance) {
      try {
        this.authInstance.off('result');
        this.authInstance = null;
        console.info('[AuthState] 认证资源已释放');
      } catch (error) {
        const err = error as BusinessError;
        console.error(`[AuthState] 释放资源失败: ${err.message}`);
      }
    }
  }

  private generateChallenge(): string {
    const length = 16;
    const array = new Uint8Array(length);
    for (let i = 0; i < length; i++) {
      array[i] = Math.floor(Math.random() * 256);
    }
    return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
  }

  private getAuthTypeName(type: userAuth.UserAuthType): string {
    switch (type) {
      case userAuth.UserAuthType.PIN: return 'PIN码';
      case userAuth.UserAuthType.FINGERPRINT: return '指纹';
      case userAuth.UserAuthType.FACE: return '人脸';
      default: return '未知';
    }
  }

  private getTrustLevelName(level: userAuth.AuthTrustLevel): string {
    switch (level) {
      case userAuth.AuthTrustLevel.ATL1: return 'S1';
      case userAuth.AuthTrustLevel.ATL2: return 'S2';
      case userAuth.AuthTrustLevel.ATL3: return 'S3';
      case userAuth.AuthTrustLevel.ATL4: return 'S4';
      default: return '未知';
    }
  }
}

/**
 * 认证能力信息
 */
interface AuthCapability {
  authType: userAuth.UserAuthType;
  trustLevel: userAuth.AuthTrustLevel;
  isAvailable: boolean;
  authTypeName: string;
  trustLevelName: string;
}

/**
 * 推荐认证方案
 */
interface RecommendedScheme {
  securityRequirement: string;
  primaryAuth: userAuth.UserAuthType;
  trustLevel: userAuth.AuthTrustLevel;
  isDowngraded: boolean;
  description: string;
}

// 使用示例:智能认证方案选择
async function demoSmartAuthSelection() {
  const monitor = new AuthStateMonitor();

  // 查询设备认证能力
  await monitor.queryDeviceAuthCapabilities();

  // 不同安全需求的推荐方案
  const lowScheme = await monitor.recommendAuthScheme('low');
  const mediumScheme = await monitor.recommendAuthScheme('medium');
  const highScheme = await monitor.recommendAuthScheme('high');
  const criticalScheme = await monitor.recommendAuthScheme('critical');

  // 使用推荐方案进行认证
  const result = await monitor.authenticateWithFullCallbacks(
    mediumScheme.primaryAuth,
    mediumScheme.trustLevel
  );

  // 释放资源
  monitor.release();
}

四、踩坑与注意事项

4.1 权限声明

生物识别认证需要声明权限:

{
  "requestPermissions": [
    {
      "name": "ohos.permission.ACCESS_BIOMETRIC",
      "reason": "$string:biometric_auth_reason",
      "usedScene": {
        "abilities": ["EntryAbility"],
        "when": "inuse"
      }
    }
  ]
}

4.2 必须提供回退方案

不是所有设备都支持生物识别,也不是所有用户都录入了生物特征。必须提供 PIN 码或密码作为回退方案

async function safeAuthenticate(): Promise<boolean> {
  const authManager = new BiometricAuthManager();

  // 先尝试指纹认证
  const fingerprintAvailable = await authManager.checkAuthAbility(
    userAuth.UserAuthType.FINGERPRINT,
    userAuth.AuthTrustLevel.ATL2
  );

  if (fingerprintAvailable) {
    const result = await authManager.authenticate(
      userAuth.UserAuthType.FINGERPRINT,
      userAuth.AuthTrustLevel.ATL2
    );
    if (result === userAuth.UserAuthResult.SUCCESS) {
      return true;
    }
  }

  // 指纹不可用或认证失败,回退到PIN码
  console.info('[SafeAuth] 回退到PIN码认证');
  const pinAvailable = await authManager.checkAuthAbility(
    userAuth.UserAuthType.PIN,
    userAuth.AuthTrustLevel.ATL2
  );

  if (pinAvailable) {
    const result = await authManager.authenticate(
      userAuth.UserAuthType.PIN,
      userAuth.AuthTrustLevel.ATL2
    );
    return result === userAuth.UserAuthResult.SUCCESS;
  }

  // 所有方式都不可用,回退到应用内密码
  console.warn('[SafeAuth] 所有系统认证方式不可用,使用应用内密码');
  return false;
}

4.3 认证实例的生命周期

每个 UserAuthInstance 只能使用一次,认证完成后必须释放:

// ❌ 错误:复用认证实例
const instance = userAuth.getUserAuthInstance(request);
await startAndAwait(instance); // 第一次认证
await startAndAwait(instance); // 报错!实例已消费

// ✅ 正确:每次认证创建新实例
async function performAuth(request: userAuth.UserAuthRequest) {
  const instance = userAuth.getUserAuthInstance(request);
  try {
    return await startAndAwait(instance);
  } finally {
    instance.off('result'); // 清理回调
  }
}

4.4 Challenge 的重要性

Challenge(挑战码)是防止重放攻击的关键。每次认证都应该生成不同的 challenge:

// ❌ 危险:使用固定challenge
const request: userAuth.UserAuthRequest = {
  challenge: 'fixed_challenge_123', // 容易被重放攻击
  authType: userAuth.UserAuthType.FINGERPRINT,
  trustLevel: userAuth.AuthTrustLevel.ATL2,
};

// ✅ 安全:每次生成随机challenge
const request: userAuth.UserAuthRequest = {
  challenge: generateRandomChallenge(), // 每次不同的挑战码
  authType: userAuth.UserAuthType.FINGERPRINT,
  trustLevel: userAuth.AuthTrustLevel.ATL2,
};

4.5 人脸识别的局限性

人脸识别在不同安全级别下的表现差异很大:

安全级别 防伪能力 2D摄像头 3D结构光
ATL1 低,可能被照片欺骗 ✅ 可用 ✅ 可用
ATL2 中,需要活体检测 ⚠️ 部分设备 ✅ 可用
ATL3 高,硬件级防伪 ❌ 不支持 ✅ 可用
ATL4 最高 ❌ 不支持 ⚠️ 部分设备

如果你的应用需要高安全级别的人脸认证,务必检查设备是否支持3D结构光。


五、HarmonyOS 6 适配

5.1 API 变更

变更项 HarmonyOS 5 HarmonyOS 6
认证实例创建 getUserAuthInstance 新增 getUserAuthInstanceV2 支持自定义UI
认证回调 on('result') 新增 on('tip') 提供实时认证提示
活体检测 隐含在trustLevel中 新增显式 livenessDetection 配置
认证意图 不支持 新增 authIntent 区分认证用途
多因素认证 需手动组合 新增 AuthSession 原生多因素支持

5.2 迁移指南

// HarmonyOS 5 写法
const request: userAuth.UserAuthRequest = {
  challenge: challenge,
  authType: userAuth.UserAuthType.FINGERPRINT,
  trustLevel: userAuth.AuthTrustLevel.ATL2,
};
const instance = userAuth.getUserAuthInstance(request);

// HarmonyOS 6 推荐写法
const requestV2: userAuth.UserAuthRequestV2 = {
  challenge: challenge,
  authType: userAuth.UserAuthType.FINGERPRINT,
  trustLevel: userAuth.AuthTrustLevel.ATL2,
  // HarmonyOS 6 新增:认证意图
  authIntent: userAuth.UserAuthIntent.VERIFY,
  // HarmonyOS 6 新增:自定义UI配置
  uiOptions: {
    dialogStyle: userAuth.DialogStyle.CLASSIC,
    customTitle: '请验证身份',
    customSubtitle: '使用指纹完成支付验证',
  },
};
const instanceV2 = userAuth.getUserAuthInstanceV2(requestV2);

5.3 实时认证提示

HarmonyOS 6 新增了认证过程中的实时提示回调,可以给用户更好的引导:

// HarmonyOS 6: 监听认证提示
instanceV2.on('tip', {
  onTip(tip: userAuth.AuthTip) {
    switch (tip) {
      case userAuth.AuthTip.FINGERPRINT_TIP_TOO_FAST:
        console.info('手指移动太快,请放慢速度');
        break;
      case userAuth.AuthTip.FINGERPRINT_TIP_TOO_SLOW:
        console.info('手指移动太慢,请稍快一些');
        break;
      case userAuth.AuthTip.FINGERPRINT_TIP_PARTIAL:
        console.info('指纹覆盖不完整,请调整手指位置');
        break;
      case userAuth.AuthTip.FACE_TIP_NOT_DETECTED:
        console.info('未检测到人脸,请正对摄像头');
        break;
      case userAuth.AuthTip.FACE_TIP_POOR_LIGHT:
        console.info('光线不足,请移到明亮处');
        break;
    }
  }
});

六、总结

核心知识点回顾

生物识别认证(userAuth)
├── 认证方式
│   ├── PIN码 ── 最基础,所有设备支持
│   ├── 指纹 ── 便捷性好,需要指纹传感器
│   └── 人脸 ── 无接触,3D结构光支持高安全级别
├── 安全级别
│   ├── ATL1(S1) ── 便捷级,可能被伪造
│   ├── ATL2(S2) ── 安全级,需要活体检测
│   ├── ATL3(S3) ── 高安全级,硬件级防伪
│   └── ATL4(S4) ── 最高安全级
├── 核心操作
│   ├── 能力检查 ── getAvailableStatus
│   ├── 创建实例 ── getUserAuthInstance
│   ├── 启动认证 ── instance.start()
│   ├── 结果回调 ── on('result')
│   └── 取消认证 ── instance.cancel()
├── 多因素认证
│   ├── 策略配置 ── 按场景定义认证策略
│   ├── 优先级选择 ── 指纹 > 人脸 > PIN
│   ├── 回退机制 ── 主方式失败自动回退
│   └── 双重验证 ── 高安全场景需要两种认证
└── 注意事项
    ├── 权限声明 ── ACCESS_BIOMETRIC
    ├── 回退方案 ── 必须提供PIN/密码回退
    ├── 实例生命周期 ── 每次认证创建新实例
    ├── Challenge ── 防止重放攻击
    └── 人脸局限 ── 2D摄像头不支持高安全级别

生物识别是安全与体验的平衡艺术。太严格,用户觉得麻烦;太宽松,安全形同虚设。掌握认证方式、安全级别和多因素组合策略,你就能为不同场景设计出恰到好处的认证方案。记住:永远提供回退方案——不是每个用户都愿意(或能够)使用生物识别。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。