钥匙环服务,打造无缝的跨设备登录体验

近些年来,随着手机技术迭代更新越来越快,用户更换手机的周期也在缩短,在这样的背景下,开发者不得不面临以下问题:

同一开发者旗下常常有多个安卓应用和多形态应用(快应用和Web应用),用户更换一个新的设备(手机或平板)后,在新设备上登录各应用时每次都需要重复输入帐号和密码,导致用户在登录阶段流失率增加,同时开发者还需要承担额外的短信成本(如用户使用短信登录)。

华为HMS Core钥匙环服务(Keyring)提供凭据管理接口(Credentials Management API),为Android手机、平板提供用户登录凭据存储和跨应用、跨应用形态、跨设备共享的能力。

钥匙环服务提供了Android APIWeb API快应用API,应用程序通过调用这些API来使用钥匙环服务。无论调用哪种形式的接口,所有的用户凭据最终都会存储在HMS Core的钥匙环服务中,以便实现统一的凭据管理能力和共享能力。

一、功能特点

钥匙环服务提供登录凭据本地储存和跨形态、跨应用共享能力。钥匙环服务将用户登录凭据加密储存在本地设备,被保存的凭据通过钥匙环服务共享至同一开发者旗下的其他快应用、Web应用和安卓应用;实现跨形态、跨应用无缝登录体验。

钥匙环服务使用端到端加密同步技术实现登录凭据跨设备同步能力。用户在新老设备上打开“凭据多设备同步”功能,就可以在新设备上免密登录同一开发者旗下的各形态应用,实现跨设备无缝登录体验。

例如,同一开发者将旗下的两个安卓应用和两个快应用接入钥匙环服务后,用户只需要在手机A和手机B上打开“凭据多设备同步”功能,手机A上登录一个应用后,用手机B登录时无需再输入帐号和密码,实现跨设备、跨应用、跨形态的无缝登录体验。

钥匙环服务,打造无缝的跨设备登录体验

二、接入优势

打造无缝登录体验

通过钥匙环服务接口获取本地存储的用户凭据,实现便捷登录。

保障数据安全可靠

用户登录凭据在设备内加密存储,在设备间通过端到端加密技术同步,云端无法解密。

降低登录流失率

简化用户登录时操作流程,降低流失率

降低运营成本

减少使用短信登录,降低运营成本

三、开发步骤

开发准备

详细准备步骤可参考华为开发者联盟官网

集成Keyring客户端

用户登录场景

1、使用一个Activity实例初始化CredentialClient,可以写在Activity的onCreate方法中。

CredentialClient credentialClient = CredentialManager.getCredentialClient(this);

2、查询是否存在可用的凭据。

List<AppIdentity> trustedAppList = new ArrayList<>();
trustedAppList.add(new AndroidAppIdentity("yourAppName", "yourAppPackageName", "yourAppCodeSigningCertHash"));
trustedAppList.add(new WebAppIdentity("youWebSiteName", "www.yourdomain.com"));
trustedAppList.add(new WebAppIdentity("youWebSiteName", "login.yourdomain.com"));
SharedCredentialFilter sharedCredentialFilter = SharedCredentialFilter.acceptTrustedApps(trustedAppList);
credentialClient.findCredential(sharedCredentialFilter, new CredentialCallback<List<Credential>>() {
    @Override
    public void onSuccess(List<Credential> credentials) {
        if (credentials.isEmpty()) {
            Toast.makeText(MainActivity.this, R.string.no_available_credential, Toast.LENGTH_SHORT).show();
        } else {
            for (Credential credential : credentials) {
            }
        }
    }
    @Override
    public void onFailure(long errorCode, CharSequence description) {
        Toast.makeText(MainActivity.this, R.string.query_credential_failed, Toast.LENGTH_SHORT).show();
    }
});

3、调用Credential.getContent获取凭据内容,在CredentialCallback获取结果。

private Credential mCredential; 
//获取的凭据
mCredential.getContent(new CredentialCallback<byte[]>() {
    @Override
    public void onSuccess(byte[] bytes) {
        String hint = String.format(getResources().getString(R.string.get_password_ok),
                new String(bytes));
        Toast.makeText(MainActivity.this, hint, Toast.LENGTH_SHORT).show();
        mResult.setText(new String(bytes));
    }
 
    @Override
    public void onFailure(long l, CharSequence charSequence) {
        Toast.makeText(MainActivity.this, R.string.get_password_failed,
                Toast.LENGTH_SHORT).show();
        mResult.setText(R.string.get_password_failed);
    }
});

4、用户输入了新凭据,调用凭据存储接口。

AndroidAppIdentity app2 = new AndroidAppIdentity(sharedToAppName,
                sharedToAppPackage, sharedToAppCertHash);
List<AppIdentity> sharedAppList = new ArrayList<>();
sharedAppList.add(app2);

Credential credential = new Credential(username, CredentialType.PASSWORD, userAuth,
                password.getBytes());
credential.setDisplayName("user_niceday");
credential.setSharedWith(sharedAppList);
credential.setSyncable(true);

credentialClient.saveCredential(credential, new CredentialCallback<Void>() {
    @Override
    public void onSuccess(Void unused) {
        Toast.makeText(MainActivity.this,
                R.string.save_credential_ok,
                Toast.LENGTH_SHORT).show();
    }
 
    @Override
    public void onFailure(long errorCode, CharSequence description) {
        Toast.makeText(MainActivity.this,
                R.string.save_credential_failed + " " + errorCode + ":" + description,
                Toast.LENGTH_SHORT).show();
    }
});

用户登出场景

1、使用一个Activity实例初始化CredentialClient,可以写在Activity的onCreate方法中。

CredentialClient credentialClient = CredentialManager.getCredentialClient(this);

2、查询是否存在可用的凭据。

List<AppIdentity> trustedAppList = new ArrayList<>();
trustedAppList.add(new AndroidAppIdentity("yourAppName", "yourAppPackageName", "yourAppCodeSigningCertHash"));
trustedAppList.add(new WebAppIdentity("youWebSiteName", "www.yourdomain.com"));
trustedAppList.add(new WebAppIdentity("youWebSiteName", "login.yourdomain.com"));
SharedCredentialFilter sharedCredentialFilter = SharedCredentialFilter.acceptTrustedApps(trustedAppList);
credentialClient.findCredential(sharedCredentialFilter, new CredentialCallback<List<Credential>>() {
    @Override
    public void onSuccess(List<Credential> credentials) {
        if (credentials.isEmpty()) {
            Toast.makeText(MainActivity.this, R.string.no_available_credential, Toast.LENGTH_SHORT).show();
        } else {
            for (Credential credential : credentials) {
                //可以对可用凭据进行进一步处理,包括:获取凭据相关信息、获取凭据内容、删除
            }
        }
    }
 
    @Override
    public void onFailure(long errorCode, CharSequence description) {
        Toast.makeText(MainActivity.this, R.string.query_credential_failed, Toast.LENGTH_SHORT).show();
    }
});

3、调用deleteCredential删除凭据,在CredentialCallback获取结果。

credentialClient.deleteCredential(credential, new CredentialCallback<Void>() {
    @Override
    public void onSuccess(Void unused) {
        String hint = String.format(getResources().getString(R.string.delete_ok),
                credential.getUsername());
        Toast.makeText(MainActivity.this, hint, Toast.LENGTH_SHORT).show();
    }
 
    @Override
    public void onFailure(long errorCode, CharSequence description) {
        String hint = String.format(getResources().getString(R.string.delete_failed),
                description);
        Toast.makeText(MainActivity.this, hint, Toast.LENGTH_SHORT).show();
    }
});

凭据共享机制

通过API参数实现凭据共享

在调用saveCredential保存凭据时,您可以通过setSharedWith设置Credential对象的属性实现凭据共享,最多支持共享给128个应用。

示例如下:

AndroidAppIdentity app1 = new AndroidAppIdentity("your android app name",
                "your android app package name", "3C:99:C3:....");
QuickAppIdentity app2 = new QuickAppIdentity("your quick app name",
                "your quick app package name", "DC:99:C4:....");
List<AppIdentity> sharedAppList = new ArrayList<>(); // 共享关系列表
sharedAppList.add(app1);
sharedAppList.add(app2);
Credential credential = new Credential("username", CredentialType.PASSWORD, true,
                "password".getBytes());
credential.setSharedWith(sharedAppList); // 设置共享关系
credentialClient.saveCredential(credential, new CredentialCallback<Void>() {
    @Override
    public void onSuccess(Void unused) {
        Toast.makeText(MainActivity.this,
                R.string.save_credential_ok,
                Toast.LENGTH_SHORT).show();
    }
    @Override
    public void onFailure(long errorCode, CharSequence description) {
        Toast.makeText(MainActivity.this,
                R.string.save_credential_failed + " " + errorCode + ":" + description,
                Toast.LENGTH_SHORT).show();
    }
});

通过Digital Asset Links资源实现凭据共享

您可以在Android应用的AndroidManifest.xml中添加凭据共享关系,方法如下:

1、在AndroidManifest.xml的节点中添加以下内容:

<application>
           <meta-data
            android:name="asset_statements"
            android:value="@string/asset_statements" />
</application>
  1. 在res\values\strings.xml中添加以下内容:
<string name="asset_statements">your digital asset links statements</string>

Digital asset links statements是一个遵循Digital Asset links规范的JSON字符串,示例如下:

[{
                   "relation": ["delegate_permission/common.get_login_creds"],
                   "target": {
                            "namespace": "web",
                            "site": "https://developer.huawei.com" // 您的网站域名
                   }
         },
         {
                   "relation": ["delegate_permission/common.get_login_creds"],
                   "target": {
                            "namespace": "android_app",
                            "package_name": "your android app package name",
                            "sha256_cert_fingerprints": [
                                     "F2:52:4D:..."
                            ]
                   }
         },
         {
                   "relation": ["delegate_permission/common.get_login_creds"],
                   "target": {
                            "namespace": "quick_app",
                            "package_name": "your quick app package name",
                            "sha256_cert_fingerprints": [
                                     "C3:68:9F:..."
                            ]
                   }
         }
]

relation属性的值固定为["delegate_permission/common.get_login_creds"],表示把凭据共享给target属性所描述的应用。

案例分享

航班管家和高铁管家集成华为钥匙环服务,为两亿用户打造无缝登录体验。

了解更多详情>>

访问华为开发者联盟官网
获取开发指导文档
华为移动服务开源仓库地址:GitHubGitee

关注我们,第一时间了解 HMS Core 最新技术资讯~

原文链接:https://www.cnblogs.com/hmscore/p/17272541.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:钥匙环服务,打造无缝的跨设备登录体验 - Python技术站

(0)
上一篇 2023年4月17日
下一篇 2023年4月17日

相关文章

  • Android Banner – ViewPager 02

    Android Banner – ViewPager 02 现在来给viewpager实现的banenr加上自动轮播 自动轮播的原理,使用handler的延迟消息来实现。 自动轮播实现如下内容 开始轮播&停止轮播 可配置轮播时长、轮播方向 通过自定义属性来配置轮播时长,方向 感知生命周期,可见时开始轮播,不可见时停止轮播 感知手指触摸,触摸按下时停止…

    Android 2023年4月17日
    00
  • Android 常用 adb 命令总结

    Android 常用 adb 命令总结 adb ( 全称为Android Debug Bridge)是一个C/S 架构命令行工具,起到调试桥的作用,是连接Android手机与PC端的桥梁,方便我们在电脑上对手机进行操作。adb 命令可用于执行各种设备操作,如安装和调试应用。 点击下载adb工具 ADB和Fastboo最新Google官方下载地址:https:…

    Android 2023年4月18日
    00
  • Android数据结构-SparseArray实现原理

    SparseArray家族 SparseArray基于键值对存储数据,key为int,value为object,简单使用如下: //声明 SparseArray<String> sparseArray= new SparseArray<>(); //增加元素,append方式 sparseArray.append(0, “myValu…

    Android 2023年4月18日
    00
  • app实现外部浏览器打开链接

    需求:安卓和IOS开发的混合app。前端使用vue,vant2,安卓使用java,ios使用的object-c。实现效果:点击按钮,下载PDF附件,app跳转到手机外部浏览器,下载附件…… 1,安卓端代码: public static void openPDFInBrowser(Context context, String url) { Uri u…

    Android 2023年4月18日
    00
  • Android报”SQLiteException”如何解决?

    下面是关于Android报”SQLiteException”异常的原因和解决办法的详细讲解。 异常原因 在进行Android应用程序开发中,我们可能会遇到SQLite数据库相关的操作,例如创建表格、插入数据、查询数据等操作。当我们在应用程序中进行这些操作时,可能会遇到”SQLiteException”异常,其原因可能如下: SQL语法错误:在进行数据库操作时…

    Android 2023年4月3日
    00
  • Android WebView 踩坑日记,字体怎么突然变小了???

    背景 最近,端内在做 webView 统一的时候,个性签名中的 WebView 替换为 CustomWebView 之后,发现字体突然变小。 一开始不知道是什么原因,通过二分法查找最近的提交,排查之后,发现是 SignatureWebView 的继承关系从 WebView 修改为 CustomWebView。revert 之后就正常了。 于是,我问自己,为什…

    Android 2023年4月18日
    00
  • Android Studio相关问题

    下载 去官网下载即可,最新版如果运行不了,可选择安装其他版本,我安装的就是4.0版本 建立项目 一般就是建立一个空项目 如果使用过idea,那么建立项目就很简单。因为Android Studio和 idea 界面都差不多,功能也类似 步骤: File——New——New Project 会出现以下画面: 然后选择 Empty Activity 再点击 Nex…

    Android 2023年5月8日
    00
  • RxJava 异常时堆栈显示不正确?解决方法都在这里

    本文首发我的博客,github 地址 大家好,我是徐公,今天为大家带来的是 RxJava 的一个血案,一行代码 return null 引发的。 前阵子,组内的同事反馈说 RxJava 在 debug 包 crash 了,捕获到的异常信息不全。(即我们捕获到的堆栈没有包含我们自己代码,都是一些系统或者 RxJava 框架的代码) 典型的一些 error 信息…

    Android 2023年4月18日
    00
合作推广
合作推广
分享本页
返回顶部