本文档介绍如何使用阿里云IDaaS的IFAA SDK for Android,涵盖SDK的集成方法、核心功能和使用示例,帮助开发者快速实现基于IFAA标准的本地生物特征认证功能。
概述
SDK & Demo 下载包内容说明
SDK & Demo 主文件:包含核心开发工具包及示例代码,助您快速集成与测试。详情请参见SDK&Demo下载。
认证服务SDK:提供完整的身份认证功能模块,支持多种验证方式,确保安全接入。
AppSignGet.apk 工具:用于一键获取指定包名应用的签名信息,简化签名配置流程。详情请参见AppSignGet.apk。
前期准备
准备工作
如果应用开启了手机号认证服务,请确保终端设备已经开启4G网络(联通、移动支持3G网络,但接口耗时会增加),手机号认证授权之后,联通电信可立即使用,移动需等待10分钟后使用。
接入流程
运行demo工程
解压Android Demo工程。
需要将包名、应用ID(appId)、应用密钥(appKey)、修改为正确的值。
修改FetchAccessTokenCallBackImpl.fetchAccessToken方法,完成获取应用授权token。
搭建开发环境
应用必须运行在Android 5.0+平台上,需要支持androidx, compileSdk 30+。
导入aar,将下载SDK拷贝到项目libs目录下。
添加依赖。
混淆忽略,若开启资源混淆,需要配置
# etas 对外提供的类不被混淆 -keep public class com.esandinfo.etas.ETASManager** { *; } -keep public class com.esandinfo.etas.EtasResult** { *; } -keep public class com.esandinfo.etas.IfaaBaseInfo {*;} -keep public class com.esandinfo.etas.IfaaBaseInfo$* {*;} -keep public class com.esandinfo.etas.IfaaCommon {*;} -keep public class com.esandinfo.etas.IfaaCommon$* {*;} -keep public class com.esandinfo.etas.model.json.** {*;} -keep public class com.esandinfo.etas.biz.** {*;} -keep public class com.esandinfo.etas.IfaaRequestBaseInfo {*;} -keep public class com.esandinfo.etas.callback.** {*;} -keep public class com.esandinfo.etas.utils.IfaaClient {*;} # ifaa 原始接⼝不被混淆 -keep class org.ifaa.** {*;} # 保留所有的本地native⽅法不被混淆 -keepclasseswithmembernames class * { native <methods>; } #号码认证配置 -keep public class R.drawable.authsdk* -keep public class R.layout.authsdk* -keep public class R.anim.authsdk* -keep public class R.id.authsdk* -keep public class R.string.authsdk* -keep public class R.style.authsdk* #SDK不被混淆 -keep class com.idsmanager.doraemonlibrary.** {*;}
权限添加。
<uses-permission android:name="android.permission.INTERNET" /> <!--网络权限--> <uses-permission android:name="android.permission.USE_FINGERPRINT" /> <!--指纹权限--> <uses-permission android:name="android.permission.MANAGE_FINGERPRINT" /> <!--指纹管理权限--> <uses-permission android:name="cn.org.ifaa.permission.USE_IFAA_MANAGER" /> <!--⼈脸权限--> <uses-permission android:name="android.permission.USE_FACERECOGNITION" /> <uses-permission android:name="oppo.permission.USE_FACE" /> <!--个别⼚商⼈脸权限--> <uses-permission android:name="android.permission.CAMERA" /><!--相机权限,需要⽤户进⾏授权--> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- 检查wifi网络状态 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 检查网络状态 --> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <!-- 切换网络通道 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 本地信息缓存 --> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <!-- 开关Wi-Fi状态,解决中国机型移动网络权限问题需要 -->
网络权限配置,修改AndroidManifest.xml。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.idsmanager.doraemondemoactivity"> ... <application ... android:networkSecurityConfig="@xml/network_security_config" > ... </manifest>
在res目录下创建xml目录以及network_security_config.xml文件。
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true" /> <domain-config cleartextTrafficPermitted="true" > <domain includeSubdomains="true">enrichgw.10010.com</domain> <!-- 联通内部5G请求域名,开发者需要添加 --> <domain includeSubdomains="true">onekey.cmpassport.com</domain> <!-- 移动内部请求域名,开发者需要添加 --> </domain-config> </network-security-config>
添加Activity 声明。在AndroidManifest.xml添加Activity声明。
<!--联通电信授权页--> <!--如果不需要使用窗口模式,不要使用authsdk_activity_dialog主题,会出现异常动画--> <!--如果需要使用authsdk_activity_dialog主题,则screenOrientation一定不能指定明确的方向, 比如portrait、sensorPortrait,在8.0的系统上不允许窗口模式指定orientation,会发生Crash,需要指定为behind, 然后在授权页的前一个页面指定具体的orientation--> <!-- 使用弹窗模式必须添加。--> <activity android:name="com.mobile.auth.gatewayauth.LoginAuthActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:exported="false" android:launchMode="singleTop" android:theme="@style/authsdk_activity_dialog" /> <!--二次弹窗界面--> <activity android:name="com.mobile.auth.gatewayauth.PrivacyDialogActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:exported="false" android:launchMode="singleTop" android:screenOrientation="behind" android:theme="@style/authsdk_activity_dialog" /> <!--协议页面webview--> <activity android:name="com.mobile.auth.gatewayauth.activity.AuthWebVeiwActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:exported="false" android:launchMode="singleTop" android:screenOrientation="behind" />
Support 包。
androidx.appcompat:appcompat:1.3.1
com.android.support.constraint:constraint-layout:1.0.2.
或者更高版本。
获取app md5 签名值。使用Android studio gradle,点击signingReport,得到MD5签名值,将冒号去掉并转小写。
说明debug包和release包签名是不一样的,避免用debug的签名值用于生产测试。
SDK 调用说明
需要在APP中集成安全认证客户端SDK,并在服务端完成API对接。应用密钥和服务密钥获取请查看应用管理。
IFAA认证SDK方法说明
初始化
此接口需要开发者调用服务端SDK的获取应用授权Token接口,自定义回调函数,然后通过FetchAccessTokenCallBackImpl回传给移动端SDK
/**
* 初始化 DoraemonManager
*
* @param context
* @param appId 应用密钥,找到安全认证应用,应用详情中拷贝 应用ID
* @param appKey 应用密钥,找到安全认证应用,点击复制密钥
* @param fetchAccessTokenCallBack 获取accessToken回调
*/
DoraemonManager.init(context, appId, appKey, new FetchAccessTokenCallBackImpl(), new DoraemonCallback() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, "DoraemonManager init faild", e);
MainActivity.this.showToast("SDK初始化失败!" + e.getMessage());
}
@Override
public void onSuccess(Object data) {
Log.e(TAG, "DoraemonManager init success");
MainActivity.this.showToast("SDK初始化成功!");
}
});
FetchAccessTokenCallBackImpl 需要获取AccessToken后返回给SDK,示例如下
public class FetchAccessTokenCallBackImpl implements FetchAccessTokenCallBack {
private static final String TAG = FetchAccessTokenCallBackImpl.class.getSimpleName();
/**
* 获取AccessToken回调方法
*
* @return
*/
@Override
public AccessTokenInfoResult fetchAccessToken(FetchAccessTokenRequest fetchAccessTokenRequest) {
AccessTokenInfoResult callbackResult = new AccessTokenInfoResult();
try {
AccessTokenInfo accessTokenInfo =new AccessTokenInfo();
/**
* TODO:获取应用授权Token
* 需要根据文档开发后端接口获取,获取后返回接口
* Token必须是同步获取的
* https://help.aliyun.com/zh/idaas/security-authentication/developer-reference/fetchaccesstoken?spm=a2c4g.11186623.0.i1
*/
accessTokenInfo.setAccess_token(?);
accessTokenInfo.setRefresh_token(?);
accessTokenInfo.setExpires_in(?);
callbackResult.setSuccess(true);
callbackResult.setMessage("获取accessToken成功。");
callbackResult.setAccessTokenInfo(accessTokenInfo);
} catch (Exception e) {
Log.e(TAG, "getAccessTokenRun exception", e);
callbackResult.setSuccess(false);
callbackResult.setMessage(e.getMessage());
}
return callbackResult;
}
}
生物识别注册(指纹、人脸)
/**
* 生物识别注册
* @param ifaaAuthTypeEnum
* @param userID
* @param doraemonCallback
*/
DoraemonManager.ifaaRegist(IfaaBaseInfo.IFAAAuthTypeEnum.AUTHTYPE_FINGERPRINT, userID, new DoraemonCallback() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, "Finger regist faild", e);
MainActivity.this.showToast("指纹注册失败!" + e.getMessage());
}
@Override
public void onSuccess(Object data) {
Log.e(TAG, "Finger regist success");
MainActivity.this.showToast("指纹注册成功!" + data);
}
});
生物识别登录(指纹、人脸)
/**
* 生物识别登录
*
* @param ifaaAuthTypeEnum
* @param userID
* @param doraemonCallback
*/
DoraemonManager.ifaaLogin(IfaaBaseInfo.IFAAAuthTypeEnum.AUTHTYPE_FINGERPRINT, userID, new DoraemonCallback() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, "Finger login faild", e);
if (e instanceof AppException) {
MainActivity.this.showToast("指纹登录失败!code=" + ((AppException) e).getCode() + " message=" + e.getMessage());
} else {
MainActivity.this.showToast("指纹登录失败!" + e.getMessage());
}
}
@Override
public void onSuccess(Object data) {
Log.e(TAG, "Finger login success");
MainActivity.this.showToast("指纹登录成功!" + data);
}
});
获取支持的生物识别类型
/**
* 获取支持的生物识别类型
*
* @param context 上下文
* @return
*/
List<IfaaBaseInfo.IFAAAuthTypeEnum> supportBIOTypes = DoraemonManager.getSupportBIOTypes(MainActivity.this);
生物识别注销
/**
* 生物识别注销
* @param ifaaAuthTypeEnum 认证类型
* @param userID 用户ID
* @param doraemonCallback 回调方法
*/
DoraemonManager.ifaaCancelRegist(authtypeFingerprint, userID, new DoraemonCallback() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, "Finger regist faild", e);
MainActivity.this.showToast("注销失败!" + e.getMessage());
}
@Override
public void onSuccess(Object data) {
Log.e(TAG, "Finger regist success");
MainActivity.this.showToast("注销成功!" + data);
}
});
获取SDK版本号
DoraemonManager.getVersion()
校验JwtToken
最后需要校验JwtToken来确保此次认证结果真实有效。