最近,我的老板突然要求我去研究鸿蒙系统里的FIDO免密认证功能,还要求我把它集成到公司的一个应用里,开发免密登录和支付的功能。当时拿到这个任务的时候,我的第一反应是:这什么鬼东西?完全没接触过这种技术,但这毕竟是老板交代的任务,我也只能硬着头皮上了。虽然心里忐忑,但我知道,开发人员的成长往往就是在这种“被逼无奈”的情况下才得以加速的,所以我决定把它当成一次挑战和学习的机会,迎难而上。
为了搞懂这个功能,我首先查了一堆官方文档和相关资料,总算弄明白了FIDO的概念——简单来说,它是一种免密认证方式,通过指纹、人脸这些生物特征代替传统的密码,用起来非常方便。鸿蒙系统里的FIDO支持免密登录和免密支付,非常适合做用户体验提升。所以我开始深入研究文档,先从最基础的API入手,希望一步一步地把这个功能实现出来。
首先,我需要导入FIDO模块,这样我们才能在代码里使用这些FIDO功能。模块的导入非常简单,代码如下:
import { fido } from '@kit.OnlineAuthenticationKit';
导入模块之后,我要做的第一件事就是获取设备支持的认证器信息,也就是看看当前设备能不能用指纹或者人脸认证,这个步骤很重要,因为如果设备不支持,那免密认证的功能就根本没法用。我写了以下代码来实现这个部分:
import { BusinessError } from '@kit.BasicServicesKit';
// 使用this.uiContext需要获取页面UIAbility的Context,一个页面获取一次即可
// 方法:uiContext:common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
try {
let discoverData: fido.DiscoveryData = await fido.discover(this.uiContext);
console.info("Succeeded in doing discover");
} catch (error) {
const err: BusinessError = error as BusinessError;
console.error(`Failed to call discover. Code is ${err.code}, message is ${err.message}`);
}
通过这个代码,我调用了fido.discover()方法,它会返回当前设备支持的认证器信息,比如支持指纹还是人脸,甚至支持的具体协议版本等等。这段代码里的this.uiContext是页面的上下文,调用这个API必须要用到它,因此确保上下文的正确获取是非常关键的一个步骤。刚开始的时候,我在获取上下文的部分踩了不少坑,导致总是报错,后来查了很多资料,才终于搞明白了。
下一步,我需要检测用户策略的开启状态,以确保用户的认证策略符合要求,这一步主要是为了检查用户设备是否开启了某些必要的安全策略。如果用户的策略不符合要求,那免密认证可能会失败。这里我用到了fido.checkPolicy()这个API,代码如下:
// 从FIDO服务器获取报文message
let uafMessage: fido.UAFMessage = {
uafProtocolMessage: message, // message为从FIDO服务器获取的检查策略报文
additionalData: ""
};
// 使用this.uiContext需要获取页面UIAbility的Context,一个页面获取一次即可
try {
await fido.checkPolicy(this.uiContext, uafMessage);
console.info("Succeeded in doing checkPolicy.");
} catch (error) {
const err: BusinessError = error as BusinessError;
console.error(`Failed to call checkPolicy. Code is ${err.code}, message is ${err.message}`);
}
这段代码里,我构造了一个UAFMessage对象,这个对象里包含了从FIDO服务器获取的检查策略的报文,然后调用了fido.checkPolicy()来检查用户设备的策略是否满足要求。这一步主要是为了确保设备本身具备足够的安全性,比如开启了生物特征认证或者其他必要的安全设置。在这个过程中,我碰到的最大问题是如何获取和构造正确的UAFMessage对象,花了不少时间才弄清楚每个字段的意义和作用。
接下来最关键的一步,就是处理用户的认证请求,这就是FIDO免密认证的核心部分。当用户要进行免密登录或者支付时,客户端会向FIDO服务器发起认证请求,服务器返回一个报文,我们需要对这个报文进行处理,最终完成用户的认证操作。代码如下:
import { BusinessError } from '@kit.BasicServicesKit';
// 从FIDO服务器获取报文message
let uafMessage: fido.UAFMessage = {
uafProtocolMessage: message, // message为从FIDO服务器获取的报文
additionalData: ""
};
let channelBinding: fido.ChannelBinding = {};
// 使用this.uiContext需要获取页面UIAbility的Context,一个页面获取一次即可
try {
let messageResp = await fido.processUAFOperation(this.uiContext, uafMessage, channelBinding);
console.info("Succeeded in doing processUAFOperation.");
} catch (error) {
const err: BusinessError = error as BusinessError;
console.error(`Failed to call processUAFOperation. Code is ${err.code}, message is ${err.message}`);
}
在这里,我调用了fido.processUAFOperation()来处理从FIDO服务器返回的认证请求报文,完成了用户的免密操作。在这个过程中,我遇到的一个问题是如何处理channelBinding,这个参数是可选的,用于确保传输通道的安全性。对于初次接触这个功能的人来说,这部分内容可能比较抽象,但其实可以简单理解为,它是用来确保通信过程中的数据安全的。
整个开发过程下来,遇到了不少坑,比如context的获取、Promise的异步处理、还有FIDO协议本身的一些细节。尤其是在处理异步操作时,Promise的链式调用让我一开始有点摸不着头脑,总是搞不清楚到底该怎么写才能确保所有步骤都按顺序执行。最让我崩溃的是,每次出错后,报错信息并不直观,通常只会返回一个错误码,我只能一个个错误码去查文档,逐步排查问题,好在最终把这些坑都填完了。
最后,当我成功完成了免密登录和支付的开发,跑起来自然流畅,用户只需要轻轻一扫指纹或者看一下手机屏幕,就可以完成登录和支付,体验非常好。看到自己辛苦的成果能够顺利运行,心里还是非常有成就感的。老板对我这个成果非常满意,甚至当着全组的面夸了我,说以后这块功能的开发就交给我了。
虽然整个过程有些艰辛,但通过这个项目,我对鸿蒙系统的FIDO免密认证有了更深的理解,也学到了很多关于异步编程和安全认证的知识,尤其是如何编写更健壮的异步代码、如何处理可能出现的各种错误情况。通过一次次的调试和改进,我对代码的理解也更加深入了。这次的经历让我意识到,作为一个开发者,面对新技术时不要害怕,勇敢去尝试,哪怕过程曲折,但每一个解决的问题,都是能力的提升和积累。
希望这篇文章能够给正在开发FIDO功能的小伙伴们提供一些帮助,让你们少踩一些我踩过的坑。如果你也遇到了类似的问题,不妨参考一下这些代码和我的思路,相信你也能顺利搞定它。
当然也希望大家关注我,有问题我们一起交流~!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。