1. 概述
官网SDK&Demo下载后进行解压,解压后包含:
具体认证服务SDK
AppSignGet.apk,用来获取对应包名的APP签名信息
2. 前期准备
2.1 准备工作
如果应用开启了手机号认证服务,请确保终端设备已经开启4G网络(联通、移动支持3G网络,但接口耗时会增加),手机号认证授权之后,联通电信可立即使用,移动需等待10分钟后使用。
2.2 接入流程
2.3 运行demo工程
解压Android Demo工程
需要将包名、应用ID(appId)、应用密钥(appKey)、修改为正确的值。
修改FetchAccessTokenCallBackImpl.fetchAccessToken方法,完成获取应用授权token。
2.4 搭建开发环境
应用必须运行在Android 5.0+平台上,需要支持androidx, compileSdk 30+。
2.4.1 导入aar
将下载SDK拷贝到项目libs目录下
2.4.2 添加依赖
2.4.3 混淆忽略
若开启资源混淆,需要配置
# 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.** {*;}
2.4.4 权限添加
<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状态,解决中国机型移动网络权限问题需要 -->
2.4.5 网络权限配置
修改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" />
2.4.6 Support 包
androidx.appcompat:appcompat:1.3.1
com.android.support.constraint:constraint-layout:1.0.2.
或者更高版本
2.4.7 获取app md5 签名值
使用Android studio gradle,点击signingReport,得到MD5签名值,将冒号去掉并转小写。
debug包和release包签名是不一样的,避免用debug的签名值用于生产测试。
3. SDK 调用说明
需要在APP中集成安全认证客户端SDK,并在服务端完成API对接。应用密钥和服务密钥获取请查看应用管理。
3.1 IFAA认证SDK方法说明
3.1.1 初始化
此接口需要开发者调用服务端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;
}
}
3.1.2 生物识别注册(指纹、人脸)
/**
* 生物识别注册
* @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);
}
});
3.1.3 生物识别登录(指纹、人脸)
/**
* 生物识别登录
*
* @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);
}
});
3.1.4 获取支持的生物识别类型
/**
* 获取支持的生物识别类型
*
* @param context 上下文
* @return
*/
List<IfaaBaseInfo.IFAAAuthTypeEnum> supportBIOTypes = DoraemonManager.getSupportBIOTypes(MainActivity.this);
3.1.5 生物识别注销
/**
* 生物识别注销
* @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);
}
});
3.1.6 获取SDK版本号
DoraemonManager.getVersion()
3.2 校验JwtToken
最后需要校验JwtToken来确保此次认证结果真实有效。