一、背景
在鸿蒙开发登录场景中,为拦截恶意登录(如频繁输错密码、机器批量尝试),需接入顶象验证码SDK做前置风控校验:用户完成验证码交互后生成有效token,业务登录接口校验token合法性后,再执行登录逻辑。本文基于该场景,总结HarmonyOS NEXT下第三方SDK(顶象验证码)的接入流程。
二、顶象验证码简介
顶象验证码包含两类核心产品(需根据场景选择):
-
智能无感验证:无需用户手动操作,基于设备指纹、行为特征、访问频率等自动校验,正常用户无感知通过,适合高频操作场景;
-
滑动/点选验证:用户需完成简单交互(如滑动滑块),适合高风险场景(如频繁输错密码后触发)。 该文章总结"滑动验证"在鸿蒙中的接入,其核心价值是:前端完成交互生成token,后端校验token有效性,阻断机器操作,兼顾安全性与用户体验。
三、开发前准备
总结:AppID+SDK+网络权限
3.1 获取 AppID
流程:注册顶象--->开通无感验证服务--->获取APPID--->接入成功后查看统计数据
官网链接:https://www.dingxiang-inc.com/docs/detail/captcha#doc-h3-13

3.2、SDK下载与引用
备注:此种方法是手动引入
官网里面有提供SDK文件,下载后在项目中新建一个目录进行保存

在需要使用的模块文件中oh-package.json5里面引入顶象SDK

3.3 配置网络权限
顶象验证码需调用网络接口,需在模块级`module.json5`中静态声明权限:
TypeScript
"requestPermissions": [
{
"name": 'ohos.permission.INTERNET',
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "inuse"
}
}
],
四、具体实现
示例代码:点击按钮出现验证码弹窗,调用CaptChaview子组件并注册回调即完成初始化
说明:
view.init("")填写申请的APPID
view.startToLoad(...) 方法,是触发验证码加载 / 验证接口请求的入口(返回的 "成功 / 失败" 结果)
核心逻辑:
点击登录按钮触发验证码弹窗;
初始化CaptchaView(传入正式AppID);
完成交互后获取token,传给登录接口;
后端校验token有效性,通过则执行登录。
完整示例代码:
TypeScript
import { CaptchaView, CaptchaViewController, JsonValueType } from 'dx.captcha'
import { HashMap } from '@kit.ArkTS';
@Entry
@Component
struct Index {
@State buttonText: string = '点击出现顶象验证码'
private config: HashMap<string, JsonValueType> = new HashMap();
/**
* 验证码弹窗
*/
private captchaDialogController = new CustomDialogController({
alignment: DialogAlignment.Center,
customStyle: true,
builder: this.captchaBuilder
})
// 验证码布局
@Builder
captchaBuilder() {
Column() {
Column() {
CaptchaView({
callBack: (view: CaptchaViewController) => {
view.init("e83bb4b2069d516f9f0798584e0ac2c1")
view.initConfig(this.config)
view.startToLoad((event: string, args: JsonValueType) => {
console.log('lucy== event', event, JSON.stringify(event))
if (event === "success") {
if (args instanceof HashMap) {
this.buttonText = '验证码验证成功'
console.log('lucy== 处理成功的操作')
}
this.captchaDialogController.close()
}
}, 'success', 'fail')
}
})
}
.padding({
left: 10,
right: 10,
top: 10,
bottom: 10
})
.backgroundColor(Color.White)
.borderRadius(10)
Button()
.margin({ top: 20 })
.onClick(() => {
this.captchaDialogController.close()
})
.backgroundImage($r("app.media.login_dialog_captcha_ic_close"))
.backgroundImagePosition(Alignment.Center)
.backgroundColor(Color.Transparent)
}
.backgroundColor(Color.Transparent)
}
build() {
Column() {
Button(this.buttonText)
.onClick(() => {
this.captchaDialogController.open()
})
}
.width('100%')
.height('100%')
}
}