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

钥匙环,服务,打造,无缝,设备,登录,体验 · 浏览次数 : 288

小编点评

**Android App Identity** ```java AppIdentity app1 = new AppIdentity(...); AppIdentity app2 = new AppIdentity(...); ``` **Credential** ```java Credential credential = new Credential(...); credential.setSharedWith(...); ``` **Digital Asset Links** ```json { "relation": ["delegate_permission/common.get_login_creds"], "target": { "namespace": "web", "site": "https://developer.huawei.com" } } ``` **Android Manifest** ```xml ``` **其他** * 通过 Digital Asset Links 资源实现凭据共享您可以在Android应用的AndroidManifest.xml中添加凭据共享关系。 *案例分享航班管家和高铁管家集成华为钥匙环服务,为两亿用户打造无缝登录体验。

正文

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

同一开发者旗下常常有多个安卓应用和多形态应用(快应用和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 最新技术资讯~

与钥匙环服务,打造无缝的跨设备登录体验相似的内容:

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

近些年来,随着手机技术迭代更新越来越快,用户更换手机的周期也在缩短,在这样的背景下,开发者不得不面临以下问题: 同一开发者旗下常常有多个安卓应用和多形态应用(快应用和Web应用),用户更换一个新的设备(手机或平板)后,在新设备上登录各应用时每次都需要重复输入帐号和密码,导致用户在登录阶段流失率增加,

bug之safari输入框

## 目录 - [前言](#前言) - [排查发](#排查发) - [解决方案](#解决方案) #### 前言 在开发中发现一个Safari才会有的bug,文本输入框中会显示密码框才有的钥匙图标🔑,图示如下: ![](https://img2023.cnblogs.com/blog/925025/

Net6之Jwt认证+Bearer认证 2.0

以前接触过,写过博客,第二次再写有了新的体会。第一次博客:https://www.cnblogs.com/zhang-3/p/16184067.html 过程: 生成token令牌(钥匙) 添加bearer认证 (验证钥匙是否正确) 给接口或控制器添加验证 (锁) 给接口添加显示的小锁 1.引入包:

码农的转型之路-全力以赴升级物联网浏览器(IoTBrowser)

在人生的重要时刻,我站在了毕业的门槛上,望着前方的道路,心中涌动着对未来的无限憧憬与些许忐忑。面前,两条道路蜿蜒伸展:一是继续在职场中寻求稳定,一是勇敢地走出一条属于自己的创新之路。尽管面临年龄和现实的挑战,我仍旧选择勇往直前,用技术这把钥匙,开启新的人生篇章。 回首过去,我深知时间宝贵,精力有限。

[转帖]公钥基础设施(PKI,Public Key Infrastructure)闲谈

https://zhuanlan.zhihu.com/p/384436119 背景 在现实空间中,人类的活动范围和接触人的范围有限,人和人最初的信任是建立在小团体或部落内部。随着全球化进展,人类的活动已经遍布全球,通信极度发达,能够低延迟的在地球的两端进行通话,甚至是太空与地面的通话(参考:卫星互联

密钥封装和公钥加密的联系和区别?

密钥封装和公钥加密的联系和区别? 转载&学习:https://www.zhihu.com/question/443779639 先理解下面这句话: 密钥封装机制是面向的互联网应用,最大的用处是网络连接时建立双方的临时会话密钥。既然是应用就要考虑到网络传输的协议,协议支持的包大小是有限制的,如果公钥加

椭圆曲线加密算法中公钥与私钥互换性分析

椭圆曲线加密算法(ECC)中,公钥与私钥具有固定的功能分工,不可互换使用。公钥用于加密和验证,私钥用于解密和签名,确保系统安全性和协议兼容性。任何试图互换角色的尝试都将导致严重的安全风险和实施困难。

[转帖]SQL Server各版本序列号/激活码/License/秘钥

https://www.cnblogs.com/cqpanda/p/16184853.html SQL Server 2019# Enterprise:HMWJ3-KY3J2-NMVD7-KG4JR-X2G8GEnterprise Core:2C9JR-K3RNG-QD4M4-JQ2HR-8468J

[转帖]ubuntu apt-get update时报错:由于没有公钥,无法验证下列签名: NO_PUBKEY 40976EAF437D05B5 E: 仓库...

在使用apt-get update 更新ubuntu时,出现下面的错误: W: GPG 错误:http://mirrors.aliyun.com/ubuntu xenial InRelease: 由于没有公钥,无法验证下列签名: NO_PUBKEY 40976EAF437D05B5 NO_PUBKE

[转帖]CA证书介绍与格式转换

https://www.cnblogs.com/librarookie/p/16330406.html 概念# PKCS 公钥加密标准(Public Key Cryptography Standards, PKCS),此一标准的设计与发布皆由RSA资讯安全公司(英语:RSA Security)所制定