开天辟地 HarmonyOS(鸿蒙) - 华为账号: 华为账号的默认登录

源码 https://github.com/webabcd/HarmonyDemo
作者 webabcd

开天辟地 HarmonyOS(鸿蒙) - 华为账号: 华为账号的默认登录

示例如下:

pages\account\HuaweiDefaultLoginDemo.ets

/*
 * 华为账号的默认登录
 *
 * 关于示例代码,请参见 /HarmonyDemo/huaweilogindemo 目录中的 /huaweilogindemo/entry/src/main/ets/HuaweiDefaultLogin.ets
 * 关于配置与证书之类的说明,请参见 /entry/src/main/ets/pages/account/readme.txt
 */

import { TitleBar } from '../TitleBar'

@Entry
@Component
struct HuaweiDefaultLoginDemo {

  @State message: string = "请参见 /HarmonyDemo/huaweilogindemo 目录中的 /huaweilogindemo/entry/src/main/ets/HuaweiDefaultLogin.ets 中的示例"

  build() {
    Column({space:10}) {
      TitleBar()
      Text(this.message)
    }
  }
}

\huaweilogindemo\entry\src\main\ets\pages\HuaweiDefaultLogin.ets

/*
 * 本例用于演示华为账号的默认的登录体验
 * 登录后可以拿到 openID, unionID 等,以及华为账号头像和昵称等
 */

import { authentication } from '@kit.AccountKit';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct HuaweiDefaultLogin {

  @State message: string = '';

  /*
   * LoginWithHuaweiIDRequest - 华为账号登录请求对象
   *   authentication.HuaweiIDProvider().createLoginWithHuaweiIDRequest() - 创建一个 LoginWithHuaweiIDRequest 对象
   *   forceLogin - 如果之前未在系统中登录华为账号,是否弹出默认登录页
   *     false - 如果之前未在系统中登录华为账号,则返回异常
   *     true - 如果之前未在系统中登录华为账号,则弹出默认登录页
   * AuthenticationController - 用于控制华为账号登录
   *   authentication.AuthenticationController() - 创建一个 AuthenticationController 对象
   *   authentication.AuthenticationController(context) - 创建一个 AuthenticationController 对象(如果需要弹出默认登录页,则必须要传 context 参数)
   *   executeRequest() - 执行指定的 LoginWithHuaweiIDRequest 请求,返回一个 LoginWithHuaweiIDResponse 对象
   * LoginWithHuaweiIDResponse - 华为账号登录的结果
   *   data - 一个 LoginWithHuaweiIDCredential 对象
   * LoginWithHuaweiIDCredential - 当前登录的华为账号的相关信息
   *   authorizationCode - 临时凭据,用于获取 Access Token,有效时间 5 分钟
   *   idToken - JWT(JSON Web Token)格式的字符串,包含了一些用户信息
   *   openID - 华为账号用户在不同的应用中的身份ID,同一个用户,不同的应用,OpenID 值不同
   *   unionID - 华为账号用户在同一个开发者账号下的应用中的身份ID,同一个用户,同一个开发者账号下管理的不同应用,UnionID 值相同
   */
  // 使用当前在系统中登录的华为账号做静默登录,如果之前未在系统中登录华为账号,则返回异常
  private login1() {
    this.message = "";

    const loginRequest = new authentication.HuaweiIDProvider().createLoginWithHuaweiIDRequest();
    loginRequest.forceLogin = false;

    const controller = new authentication.AuthenticationController();
    controller.executeRequest(loginRequest).then((data: authentication.LoginWithHuaweiIDResponse) => {
      this.message += `登录成功\n`
      const loginWithHuaweiIDCredential = data.data;
      if (loginWithHuaweiIDCredential) {
        this.message += `authorizationCode: ${loginWithHuaweiIDCredential.authorizationCode}\n`
        this.message += `idToken: ${loginWithHuaweiIDCredential.idToken}\n`
        this.message += `openID: ${loginWithHuaweiIDCredential.openID}\n`
        this.message += `unionID: ${loginWithHuaweiIDCredential.unionID}\n`
      }
    }).catch((error: BusinessError) => {
      this.message += `errCode:${error.code}, errMessage:${error.message}\n`
      if (error.code === authentication.AuthenticationErrorCode.ACCOUNT_NOT_LOGGED_IN) {
        this.message += `用户未登录华为账号\n`
      }
    });
  }

  // 使用当前在系统中登录的华为账号做静默登录,如果之前未在系统中登录华为账号,则弹出默认登录页
  private login2() {
    this.message = "";

    const loginRequest = new authentication.HuaweiIDProvider().createLoginWithHuaweiIDRequest();
    loginRequest.forceLogin = true;

    const controller = new authentication.AuthenticationController(this.getUIContext().getHostContext());
    controller.executeRequest(loginRequest).then((data: authentication.LoginWithHuaweiIDResponse) => {
      this.message += `登录成功\n`
      const loginWithHuaweiIDCredential = data.data;
      if (loginWithHuaweiIDCredential) {
        this.message += `authorizationCode: ${loginWithHuaweiIDCredential.authorizationCode}\n`
        this.message += `idToken: ${loginWithHuaweiIDCredential.idToken}\n`
        this.message += `openID: ${loginWithHuaweiIDCredential.openID}\n`
        this.message += `unionID: ${loginWithHuaweiIDCredential.unionID}\n`
      }
    }).catch((error: BusinessError) => {
      this.message += `errCode:${error.code}, errMessage:${error.message}\n`
      if (error.code === authentication.AuthenticationErrorCode.ACCOUNT_NOT_LOGGED_IN) {
        this.message += `用户未登录华为账号\n`
      }
    });
  }

  /*
   * AuthorizationWithHuaweiIDRequest - 华为账号授权请求对象
   *   authentication.HuaweiIDProvider().createAuthorizationWithHuaweiIDRequest() - 创建一个 AuthorizationWithHuaweiIDRequest 对象
   *   forceLogin - 如果之前未在系统中登录华为账号,是否弹出默认登录页
   *     false - 如果之前未在系统中登录华为账号,则返回异常
   *     true - 如果之前未在系统中登录华为账号,则弹出默认登录页
   * AuthenticationController - 用于控制华为账号授权
   *   authentication.AuthenticationController() - 创建一个 AuthenticationController 对象
   *   authentication.AuthenticationController(context) - 创建一个 AuthenticationController 对象(如果需要弹出默认登录页,则必须要传 context 参数)
   *   executeRequest() - 执行指定的 AuthorizationWithHuaweiIDRequest 请求,返回一个 AuthorizationWithHuaweiIDResponse 对象
   * AuthorizationWithHuaweiIDResponse - 华为账号授权的结果
   *   data - 一个 AuthorizationWithHuaweiIDCredential 对象
   * AuthorizationWithHuaweiIDCredential - 当前登录的华为账号的相关信息
   *   avatarUri - 头像地址
   *   nickName - 昵称
   */
  // 使用当前在系统中登录的华为账号做静默登录,如果之前未在系统中登录华为账号,则弹出默认登录页
  // 然后获取华为账号头像和昵称
  private login3() {
    this.message = "";

    const authRequest = new authentication.HuaweiIDProvider().createAuthorizationWithHuaweiIDRequest();
    authRequest.scopes = ['profile'];
    authRequest.forceAuthorization = true;

    const controller = new authentication.AuthenticationController(this.getUIContext().getHostContext());
    controller.executeRequest(authRequest).then((data: authentication.AuthorizationWithHuaweiIDResponse) => {
      this.message += `登录成功\n`
      const authorizationWithHuaweiIDCredential = data.data;
      if (authorizationWithHuaweiIDCredential) {
        this.message += `avatarUri: ${authorizationWithHuaweiIDCredential.avatarUri}\n`
        this.message += `nickName: ${authorizationWithHuaweiIDCredential.nickName}\n`
      }
    }).catch((error: BusinessError) => {
      this.message += `errCode:${error.code}, errMessage:${error.message}\n`
      if (error.code === authentication.AuthenticationErrorCode.ACCOUNT_NOT_LOGGED_IN) {
        this.message += `用户未登录华为账号\n`
      }
    });
  }

  build() {
    Column({space:10}) {
      Button("静默登录,未登录则返回异常").onClick(() => {
        this.login1();
      })
      Button("静默登录,未登录则弹出默认登录页").onClick(() => {
        this.login2();
      })
      Button("静默登录,获取华为账号头像和昵称").onClick(() => {
        this.login3();
      })

      Scroll() {
        Text(this.message)
      }.layoutWeight(1).align(Alignment.TopStart).backgroundColor(Color.Yellow).width('100%')
    }
    .width('100%')
    .height('100%')
  }
}

\entry\src\main\ets\pages\account\readme.txt

注:关于证书和华为账号登录的示例请参见 /huaweilogindemo 项目


几个概念:
AGC - AppGallery Connect
AGC 的地址 https://developer.huawei.com/consumer/cn/service/josp/agc/index.html
AGC 中的一个项目可以包含多个应用,这里所谓的项目比较类似分组的概念
.csr - 证书请求文件 Certificate Signing Request
.cer - AGC 上申请的证书文件的后缀名
.p7b - AGC 上申请的 profile 文件的后缀名
.p12 - 密钥库文件


证书相关:
1、生成证书请求文件
在 DevEco Studio 中选择 Build -> Generate Key and CSR
如果有密钥库文件(.p12)那么就选择它,如果没有则新建密钥库文件
选择好密钥库文件之后,设置一个秘钥别名(一个密钥库可以包含多个秘钥别名,一个秘钥别名对应一个 .csr 文件,后续在配置签名的时候会用到秘钥别名)
然后指定 .csr 文件的路径之后,就可以生成 .csr 文件了(建议 .csr 文件的文件名与秘钥别名一致)
注:选择保存路径的时候,最好都指向一个单独的文件夹,最终会生成一个 .p12 文件(密钥库文件),一个 .csr 文件(证书请求文件),一个名为 material 的文件夹(存放一些相关的资料)
2、在 AGC 的“证书、APP ID和Profile”中生成证书
证书类型分为“调试证书”和“发布证书”,为证书起名时,调试证书可以起名为:应用名称_debug,发布证书可以起名为:应用名称_release(注:证书的后缀名为 .cer)
选择 .csr 文件后就可以生成证书了
3、如果需要调试的话,则需要在 AGC 的“证书、APP ID和Profile”中注册调试设备,最多注册 100 个设备
获取设备的 UDID 的方法如下:
进入设备的“设置” -> “关于本机”,然后多次点击版本号,打开开发者模式
进入设备的“设置” -> “系统”,在最下方找到“开发人员选项”,然后打开“USB调试”开关
通过 hdc shell bm get --udid 获取设备的 UDID
hdc 的地址在 DevEco Studio 安装目录/sdk/default/openharmony/toolchains 中
4、在 AGC 的“证书、APP ID和Profile”中生成 profile
需要选择相关的证书
为 profile 起名时,调试 profile 可以起名为:应用名称_debug,发布 profile 可以起名为:应用名称_release(注:profile 的后缀名为 .p7b)
如果是调试 profile 还要选择已注册的设备
5、配置签名
在 DevEco Studio 中选择 File -> Project Structure -> Project -> Signing Configs 做配置(对应的配置文件为: 根目录/build-profile.json5)
调试场景时,可以使用自动签名也可以使用手动签名
发布场景时,只能使用手动签名


华为账号登录相关:
1、在 AGC 中创建相关的项目和相关的应用
2、在 AGC 中选择“我的项目”,然后点击相关的项目,然后点击相关的应用,然后在“常规”中找到指定应用的“OAuth 2.0客户端ID(凭据)”中的 Client ID
3、在本地开发项目中的 entry 模块的 module.json5 中做如下配置
"module": {
  "type": "entry",
  "metadata": [
    {
      "name": "client_id",
      "value": "从 AGC 上拿到的指定应用的“OAuth 2.0客户端ID(凭据)”中的 Client ID"
    }
  ]
}
4、配置证书指纹
在 DevEco Studio 中选择 File -> Project Structure -> Project -> Signing Configs
点击 Store file(*.p12): 最右侧的指纹按钮,然后复制证书指纹信息
在 AGC 中选择“我的项目”,然后点击相关的项目,然后点击相关的应用,然后在“常规”中找到指定应用的“SHA256证书/公钥指纹”,然后点击“添加证书指纹”,然后粘贴之前复制的证书指纹信息
5、配置公钥指纹
在 AGC 中选择“我的项目”,然后点击相关的项目,然后点击相关的应用,然后在“常规”中找到指定应用的“SHA256证书/公钥指纹”,然后点击“添加公钥指纹 (HarmonyOS API 9及以上)”,然后选择相关的公钥指纹信息即可
6、申请 scope 权限
进入 https://developer.huawei.com/consumer/cn/console/api/scopeManage 
先在左上角选择好项目和凭证(凭证名称是由应用名称和应用的 APP ID 组成的),然后再查看或申请 scope 权限
默认有 openid, profile 权限,敏感权限需要单独申请

源码 https://github.com/webabcd/HarmonyDemo
作者 webabcd

posted @ 2025-05-27 14:52  webabcd  阅读(27)  评论(0)    收藏  举报