员工身份(EIAM)

二次生物认证

# 文档说明

本文为您介绍Android客户端如何接入生物认证功能。生物认证即PC端登录时使用手机指纹/面容识别功能作为多因素认证。

用户在PC登录时选择“使用认证器作为二次认证”,此同时用户打开APP,确保登录状态和设备已绑定的情况下,App查询后台二次认证请求,如果有,APP会唤起手机生物识别确认是机主本人,同时APP会通知IDaaS服务端进行接下来的认证授权流程。

# 流程说明

绑定设备集成流程说明

  1. App客户端调用查询设备绑定状态方法,IDaaS SDK请求IDaaS服务端查询设备是否已绑定。
  2. 如果查询结果为没有绑定此设备,App客户端 调用绑定设备方法,IDaaS SDK 发起绑定流程,调起手机指纹识别/面容识别,确认是机主本人。IDaaS服务端记录本机为已绑定状态,并返回绑定成功/失败给App客户端。

二次认证流程说明

  1. 用户打开PC浏览器浏览器登录IDaaS系统,选择“使用认证器作为二次认证”,点击验证。App 客户端调用查询是否有二次认证方法,IDaaS服务端返回随机字串。
  2. App客户端拿到随机字串,用这个字串调用二次认证方法,IDaaS SDK拉起二次认证流程,调起手机指纹识别/面容识别,确认是机主本人,并发送二次认证请求到IDaaS服务端。服务端验证通过,PC网页端自动刷新状态。

解绑流程说明

  1. App客户端调用查询设备绑定状态方法,IDaaS SDK请求IDaaS服务端查询设备是否已绑定。
  2. 如果查询结果为已绑定此设备,App客户端调用解绑方法,IDaaS SDK发起解绑流程,调起手机指纹识别/面容识别,确认是机主本人,IDaaS服务端记录本机为未绑定状态,并返回解绑成功/失败给App客户端。

# 准备工作

# 获取clientID

登录IDaaS企业中心平台,点击 “资源-->应用” 选择跟自己相关的应用点击即可查看到。

# 开启二次认证

  1. 登录到IDaaS企业中心平台,点击 “认证—>认证策略”。

  2. 点击添加策略,此时会右边弹出一个策略框,输入描述,并且勾选“二次认证”和“竹云认证器(FaceID或指纹识别)”,点击确定。

  3. 如上步骤配置好后,会在登录用户中心页面,进行了一级登录后,需要二次认证的地方,会出现选项"通过竹云验证器进行验证"。

# 引入依赖包

AuthnCenter_Common-1.5.3.aar
AuthnCenter_MFA_BioVerify-1.5.3.aar
1
2

将IDaaS SDK拖入工程,并且引入方式如下:

# 配置 build.gradle

  /*begin*/
    /*  rxjava2 +  okhttp + retrofit2  */
    api 'io.reactivex.rxjava2:rxjava:2.2.10'
    api 'io.reactivex.rxjava2:rxandroid:2.1.1'
    api 'com.squareup.retrofit2:retrofit:2.6.0'
    api 'com.squareup.retrofit2:adapter-rxjava2:2.6.0'
    api 'com.squareup.retrofit2:converter-gson:2.6.0'
    api 'com.squareup.okhttp3:okhttp:4.3.1'
    api 'com.squareup.okhttp3:logging-interceptor:3.6.0'
    api 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
    api 'com.trello.rxlifecycle2:rxlifecycle-components:2.1.0'
    api 'com.alibaba:fastjson:1.2.61'

    api 'org.greenrobot:greendao:3.3.0' // add library

    implementation 'com.github.bumptech.glide:glide:4.14.2'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.14.2'
    /*end  */

    api 'io.jsonwebtoken:jjwt-api:0.11.5'
    runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
    runtimeOnly('io.jsonwebtoken:jjwt-orgjson:0.11.5') {
        exclude group: 'org.json', module: 'json' //provided by Android natively
    }

    implementation "androidx.biometric:biometric:1.1.0"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 开发集成

# SDK初始化

AuthnCenterSDK.Builder()
                .init(this)
                .setBaseUrl("https://xxx.xxx.com")      //租户域名
                .setClientId("xxxx") //租户后台应用client-id
                .isCheckSSL(false) //是否检测SSL证书
                .logEnable(false).build(); //是否打开http请求log   建议上线之后关闭
1
2
3
4
5
6

# 调用顺序说明

SDK 里面包含封装好的生物识别界面和单个业务接口,调用方可根据自己的实际业务需求进行灵活组合。

业务接口调用顺序说明。

查询绑定状态----> 查询是否有认证 ---->开启认证。

# 业务接口调用示例

查询设备绑定状态

  AuthnCenterMFA.Builder().getStatus(this, accountInfo.getIdToken(), new MFAListener<Boolean>() {
            @Override
            public void success(Boolean data) {
                 
            }

            @Override
            public void error(String s, String s1) {
                ToastUtils.ShowToast(InfoActivity.this, String.format("%s %s", s, s1));
            }
        });
1
2
3
4
5
6
7
8
9
10
11

绑定设备

        try {
           byte[] publicKey = keyStoreUtils.getPublicKey(accountInfo.getUserId()).getEncoded();
           String pk = Base64.encodeToString(publicKey, Base64.DEFAULT).replaceAll("\n", "");
            Map map = new HashMap();
           map.put("publicKey", keyStoreUtils.PublicKeyToPem(pk));

            AuthnCenterMFA.Builder().bind(this, accountInfo.getIdToken(), map, new MFAListener<Boolean>() {
                @Override
               public void success(Boolean o) {
                    ToastUtils.ShowToast(InfoActivity.this, o == true ? "绑定成功" : "绑定失败");
                }

                @Override
                public void error(String s, String s1) {
                    ToastUtils.ShowToast(InfoActivity.this, String.format("%s %s", s, s1));
                }
            });
        } catch (Exception e) {
            ToastUtils.ShowToast(InfoActivity.this, String.format("%s", e.toString()));
            e.printStackTrace();
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

解绑设备

   AuthnCenterMFA.Builder().unbind(this, accountInfo.getIdToken(), new MFAListener<Boolean>() {
            @Override
            public void success(Boolean data) {
                tv_switch.setChecked(data == true ? false : true);
                ToastUtils.ShowToast(InfoActivity.this, data == true ? "解绑成功" : "解绑失败");
            }

            @Override
            public void error(String s, String s1) {
                ToastUtils.ShowToast(InfoActivity.this, String.format("%s %s", s, s1));
            }
        });
1
2
3
4
5
6
7
8
9
10
11
12

查询是否有认证信息

        AuthnCenterMFA.Builder().getAuthentication(this, accountInfo.getIdToken(), new MFAListener<AuthenticationInfo>() {
            @Override
            public void success(AuthenticationInfo data) {

                if (data != null && !TextUtils.isEmpty(data.getRandom())) {
                    
                } else {
                    return;
                }
            }

            @Override
            public void error(String code, String msg) {

            }
        });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

开启认证


        try {
            String singMsgTmp = String.format("%s", authenticationInfo.getRandom());
            Signature signature = KeyStoreUtils.getInstance(getUserId(accountInfo.getIdToken())).initSignature();
            signature.update(singMsgTmp.getBytes());
            byte[] valueSign = signature.sign();
            String sing = Base64.encodeToString(valueSign, Base64.DEFAULT).replaceAll("\n", "");
            Map map = new HashMap();
            map.put("signature", sing);
            AuthnCenterMFA.Builder().startAuthentication(InfoActivity.this, accountInfo.getIdToken(), map, new MFAListener<Boolean>() {
                @Override
                public void success(Boolean data) {
                    if (data)
                        ToastUtils.ShowToast(mContext, "认证成功");
                    else
                        ToastUtils.ShowToast(mContext, "认证失败");
                }

                @Override
                public void error(String code, String msg) {
                    ToastUtils.ShowToast(mContext, String.format("%s %s", code, msg));
                }
            });
        } catch (Exception e) {
            ToastUtils.ShowToast(mContext, String.format("%s", e.toString()));
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

包含生物识别界面绑定调用方式

 AuthnCenterMFA.Builder().startBiometric(this, accountInfo.getIdToken(), BiometricType.BIND, new OnBiometricIdentifyCallback() {
            @Override
            public void onSucceeded() {
                ToastUtils.ShowToast(InfoActivity.this, "绑定成功");
            }

            @Override
            public void onFailed() {

            }

            @Override
            public void onError(String s, String s1) {
                ToastUtils.ShowToast(InfoActivity.this, "绑定失败" + s1);
            }

            @Override
            public void onCancel() {

            }
        });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

包含生物识别界面解绑调用方式

  AuthnCenterMFA.Builder().startBiometric(this, accountInfo.getIdToken(), BiometricType.UNBIND, new OnBiometricIdentifyCallback() {
            @Override
            public void onSucceeded() {
                ToastUtils.ShowToast(InfoActivity.this, "解绑成功");
            }

            @Override
            public void onFailed() {

            }

            @Override
            public void onError(String s, String s1) {
                ToastUtils.ShowToast(InfoActivity.this, "解绑失败" + s1);
            }

            @Override
            public void onCancel() {

            }
        });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 返回码

状态码 错误码 (error_code) 错误说明 (error_msg) 处理措施
400 IDAAS.SDK.COMMON.1001 Parameter {0} cannot be left blank
参数 {0} 不能为空
400 IDAAS.SDK.COMMON.1002 The {0} parameter format is incorrect
参数 {0} 格式错误
400 IDAAS.SDK.COMMON.1003 Device information is incomplete
设备信息不完整
400 IDAAS.SDK.COMMON.1004 Signature decryption error
签名解密错误
400 IDAAS.SDK.COMMON.1005 The {0} has failed
{0} 已失效
400 IDAAS.SDK.COMMON.1006 The {0} parameter error
{0} 参数错误
400 IDAAS.SDK.COMMON.1007 The {0} parameter type error
{0}参数类型错误
500 IDAAS.SDK.COMMON.1008 The system is busy. Try again later
系统繁忙。稍后再试
400 IDAAS.SDK.COMMON.1009 Unknown authentication configuration
未知的认证配置
400 IDAAS.SDK.COMMON.1010 Failed to obtain the enterprise center global configuration
获取企业中心全局配置失败
400 IDAAS.SDK.COMMON.1011 Failed to obtain the international area code configuration
获取国际区号配置失败
400 IDAAS.SDK.COMMON.1012 The x-client-ID is incorrect and the corresponding application cannot be found
X-client-id错误,找不到对应的应用
400 IDAAS.SDK.COMMON.1013 The corresponding user is not found
未找到对应的用户
400 IDAAS.SDK.COMMON.1014 Application private key not found
未找到应用私钥
400 IDAAS.SDK.LOGIN.1001 Error calling interface {0}
调用 {0} 接口出错
400 IDAAS.SDK.LOGIN.1002 User not bound
用户未绑定
400 IDAAS.SDK.LOGIN.1003 The user has been locked due to too many unsuccessful login attempts. It will be unlocked in {0} minutes and {1} seconds
由于多次登录失败,用户已被锁定。 它将在 {0} 分钟和 {1} 秒内解锁
400 IDAAS.SDK.LOGIN.1004 Failed to obtain the password policy
获取密码策略错误
400 IDAAS.SDK.LOGIN.1005 Invalid username or password. Remaining login attempts: {0}
无效的用户名或密码。 其余登录尝试次数:{0}
400 IDAAS.SDK.LOGIN.1006 Configuration error, unable to find wechat authentication source
配置错误,找不到微信认证源
400 IDAAS.SDK.LOGIN.1007 Configuration error, unable to find alipay authentication source
配置错误,找不到支付宝认证源
400 IDAAS.SDK.LOGIN.1008 The configuration is incorrect. The one-click login authentication source cannot be found
配置错误,无法找到一键登录认证源
400 IDAAS.SDK.SMS.1001 {0} slide base map is not initialized successfully, please check the path
{0} 滑动底图未初始化成功,请检查路径
400 IDAAS.SDK.SMS.1002 {0} verification code coordinate resolution failed
{0} 验证码坐标解析失败
400 IDAAS.SDK.SMS.1003 {0} verification code coordinate verification fails
{0} 验证码坐标校验失败
400 IDAAS.SDK.SMS.1004 The graphic verification code is incorrect
图形验证码校验错误
400 IDAAS.SDK.SMS.1005 SMS verification code verification is incorrect
短信验证码验证错误
400 IDAAS.SDK.SMS.1006 The email verification code is incorrect
邮件验证码验证错误
400 IDAAS.SDK.SMS.1007 Sending scenario does not exist
发送场景不存在
400 IDAAS.SDK.SMS.1008 Failed to send the verification code
发送验证码失败
400 IDAAS.SDK.SOCIAL.1001 The social account is unbound incorrectly
社交账号解绑错误
400 IDAAS.SDK.SOCIAL.1002 The social account has been bound, please unbind it first
社交账号已绑定,请先解绑
400 IDAAS.SDK.PWD.1001 The password length is incorrect
密码长度错误
400 IDAAS.SDK.PWD.1002 The password cannot be the username
密码不能为用户名
400 IDAAS.SDK.PWD.1003 Your password complexity is low
你的密码复杂度过低
400 IDAAS.SDK.PWD.1004 The password is weak
密码很弱
400 IDAAS.SDK.PWD.1005 The password is used before, cannot be used again
该密码已被使用过,不能再次使用
400 IDAAS.SDK.PWD.1006 Password cannot username in reverse order
密码不能是用户名的倒序
400 IDAAS.SDK.PWD.1007 The number of repeated password characters exceeded the upper limit
密码重复字符数超过限制
400 IDAAS.SDK.PWD.1008 Password cannot contain :username, phone number, email prefix, name in PinYing
密码不能包含:用户名、电话号码、邮件前缀、拼音名
400 IDAAS.SDK.MFA.1001 The mobile doesn't match the user
手机号和用户不匹配
400 IDAAS.SDK.MFA.1002 The access control policy is incorrect
访问控制策略配置错误
400 IDAAS.SDK.MFA.1003 Access control authentication source type conversion error
访问控制身份验证源类型转换错误