客户身份(CIAM)

密码登录

# 文档说明

本文为您介绍Android客户端如何接入密码登录功能。

# 流程说明

# 登录流程

集成流程说明

  1. 用户输入用户名+密码/手机号+密码/邮箱+密码点击登录按钮。

  2. APP客户端调用登录方法(4种)。

  3. IDaaS SDK调用IDaaS服务端认证。认证结果分为四种(成功,密码即将过期,密码过期,失败)。

  4. 成功情况下,IDaaS服务端返回session_token。

  5. IDaaS SDK返回session_token给APP客户端。

  6. 如果密码即将过期,IDaaS服务端返回密码即将过期参数。

  7. IDaaS SDK返回密码即将过期给APP客户端。

  8. 用户可以选择跳过修改密码或者直接修改密码。

  9. APP客户端根据用户点击按钮,调用跳过修改密码方法或者调用修改密码方法。

  10. IDaaS SDK调用IDaaS服务端跳过修改密码接口或者调用修改密码接口。

  11. IDaaS 服务端校验成功就返回session_token,失败就返回错误码。

  12. IDaaS SDK将成功失败的参数返回给APP客户端。

  13. 如果密码已经过期了,IDaaS 服务端返回给IDaaS SDK强制修改密码的参数。

  14. IDaaS SDK返回给客户端APP强制修改密码的参数。

  15. 用户被强制修改密码,APP客户端调用修改密码的方法。

  16. IDaaS SDK调用IDaaS 服务端修改密码的接口。

  17. IDaaS 服务端密码修改成功返回session_token给IDaaSSDK/密码修改失败返回错误码。

  18. IDaaS SDK密码修改成功返回session_token给APP客户端/密码修改失败返回错误码。

# 找回密码流程

集成流程说明

1.用户点击忘记密码按钮。

2.APP客户端展示找回密码页面,此页面需要APP自己提供。

3.用户输入手机号,点击获取验证码按钮。

4.APP调用滑块验证方法。

5.IDaaS SDK请求IDaaS 服务端滑块校验接口。

6.IDaaS 服务端返回滑块校验参数。

7.IDaaS SDK拉起滑块验证窗口展示。

8.用户拖动滑块验证。

9.IDaaS SDK发送滑块验证给IDaaS服务端。

10.IDaaS 服务端返回滑块校验结果。

11.IDaaS SDK返回滑块校验结果给APP客户端。

12.APP客户端用滑块token调用IDaaS SDK发送短信验证码的方法。

13.IDaaS SDK调用IDaaS 服务端发送验证码的接口。

14.IDaaS 服务端返回发送验证码结果给IDaaS SDK。

15.IDaaS SDK返回发送验证码结果给APP客户端。

16.用户收到短信验证码并且填入,点击找回密码按钮。

17.APP客户端用手机号+验证码+新密码调用IDaaS SDK的找回密码方法。

18.IDaaS SDK调用IDaaS服务端找回密码接口。

19.IDaaS服务端返回找回密码结果给IDaaS SDK。

20.IDaaS SDK返回找回密码结果给APP客户端。

# 环境搭建

# 获取clientID

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

# 密码策略设置

此设置是为了配置密码过期时间和提醒时长。

先按照下图路径到密码策略的模块。

密码过期下面可以开启:

开启后,可以按照下图所示设置密码多长时间过期,提前通知的天数。

这个设置是为了登录后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'
     /*end*/ 
        
    //公共库,必选      
    implementation(name: 'AuthnCenter_Common-1.5.3', ext: 'aar')   
    //密码登录SDK,必选
    implementation(name: ''AuthnCenter_PWDLogin-1.5.3', ext: 'aar')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 配置AndroidManifest

 <!--权限-->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEM"/>
1
2
3
4
5
6
7
8

# 初始化

AuthnCenterSDK.Builder().init(this)
        .setBaseUrl("https://xxx.idaas-xxxx.bccastle.com") //IDASS 应用二级域名
        .setClientId(zlgV9yb7CsHqaPOlsPad70S9EyEIHw7j")  //申请的应用 clientId
        .isCheckSSL(true)  //是开启SSL校验  如果是https建议开启
        .logEnable(true)  //建议集成阶段开启,上线后关闭
        .build();                                            
1
2
3
4
5
6

# 开发集成

# 内置API介绍

基本配置初始化主类AuthnCenterAPI方法简介:

/**
 * 短信验证码 -- 发送短信
 */
public void smsSend(Context context, SendSmsReq req, RequestListener listener)

/**
 * 获取国家区号    注意 如果配置了国家区号需要调用此接口获取国家区号
 */
public void getCountryCode(Context context, RequestListener listener)
1
2
3
4
5
6
7
8
9

密码登录初始化主类AuthnCenterPWDLogin方法简介:

/**
 * 用户名密码登录
 *
 * @param context 上下文
 * @param userName  用户名
 * @param password   密码
 * @param loginListener  事件回调
 */
public void userLoginRequest(Context context, String userName, String password, PWLoginListener loginListener)

/**
 * 统一用户密码登录
 *   同时支持用户名密码  手机号+密码  邮箱+密码
 * @param context 上下文
 * @param userName  用户名
 * @param password   密码
 * @param loginListener  事件回调
 */
public void userLoginAuthRequest(Context context, String userName, String password, PWLoginListener loginListener) 

/**
 * 手机号+密码
 *
 * @param context 上下文
 * @param mobile  手机号
 * @param password   密码
 * @param loginListener  事件回调
 */
public void userLoginMobilePwd(Context context, String mobile, String password, PWLoginListener loginListener)

/**
 * 邮箱+密码
 *
 * @param context 上下文
 * @param email   邮箱
 * @param password   密码
 * @param loginListener  事件回调
 */
public void userLoginEmailPwd(Context context, String email, String password, PWLoginListener loginListener)

/**
 * 短信注册
 *
 * @param context 上下文
 * @param userInfoReq  注册用户实体
 * @param loginListener  事件回调
 */
public void userRegister(Context context, UserInfoReq userInfoReq, PWLoginListener loginListener) 

/**
 * 找回密码
 *
 * @param context 上下文
 * @param findPwdReq   找回密码实体
 * @param loginListener  事件回调
 */
public void findPwd(Context context, FindPwdReq findPwdReq, PWLoginListener loginListener)

/**
 * 跳过修改密码
 *
 * @param context 上下文
 * @param stateToken stateToken
 * @param loginListener  事件回调
 */
public void skipPwd(Context context, String stateToken, PWLoginListener loginListener) 

/**
 * 强制修改密码
 *
 * @param context 上下文
 * @param pwdReq    修改密码实体
 * @param stateToken stateToken
 * @param loginListener  事件回调
 */
public void updatePwd(Context context, UpdatePwdReq pwdReq, String stateToken, PWLoginListener loginListener)
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

PWLoginListener 在登录API回调时候会返回不同的CODE码 针对不同的应用场景需要接入这自行判断并做相关业务处理。

目前只针对 密码即将过期以及已经过期会返回如下code,具体可参照接入DEMO进行参考。

code码 内置枚举值 释义
10006 SDKCodeType.SDK_PASSWORD_EXPIRED.getCode() 密码已经过期
10007 SDKCodeType.SDK_PASSWORD_WARN.getCode() 密码即将过期

# 手机国际区号获取

如果开启了国际号码支持请自行先行调用国际区号获取接口,国际区号获取接口返回配置好的国际区号列表,并附有电话号码的正则表达式。下图中就是如何配置国际区号列表和首选区号。

获取国际区号列表示例代码:

AuthnCenterAPI.Builder().getCountryCode(this, new RequestListener<CountryCodeInfoRsp>() {
    @Override
    public void success(CountryCodeInfoRsp codeInfoRsp) {
  
    }

    @Override
    public void error(String code, String errorMessage) {
    }
});
1
2
3
4
5
6
7
8
9
10

成功示例code=0,data的值:

{
	"phoneAreaCodeDefinitions": [
		{
			"areaCode": "86",
			"displayMapping": {
				"zh-TW": "中國大陸",
				"en": "China",
				"zh-CN": "中国大陆"
			},
			"countryCode": "CN",
			"mobileRegex": "^(\\+86){0,1}\\-?1\\d{10}$",
			"areaCodeSuffixes": []
		},
		{
			"areaCode": "852",
			"displayMapping": {
				"zh-TW": "中國香港",
				"en": "Hong Kong",
				"zh-CN": "中国香港"
			},
			"countryCode": "HK",
			"mobileRegex": "^(\\+852){1}\\-?0{0,1}[1,4,5,6,7,8,9](?:\\d{7}|\\d{8}|\\d{12})$",
			"areaCodeSuffixes": []
		},
		{
			"areaCode": "886",
			"displayMapping": {
				"zh-TW": "中國臺灣",
				"en": "Taiwan",
				"zh-CN": "中国台湾"
			},
			"countryCode": "TW",
			"mobileRegex": "^(\\+886){1}\\-?[6,7,9](?:\\d{7}|\\d{8})$",
			"areaCodeSuffixes": []
		},
		{
			"areaCode": "853",
			"displayMapping": {
				"zh-TW": "中國澳門",
				"en": "Macau",
				"zh-CN": "中国澳门"
			},
			"countryCode": "MO",
			"mobileRegex": "^(\\+853){1}\\-?0{0,1}[1,4,5,6,7,8,9](?:\\d{7}|\\d{8}|\\d{12})$",
			"areaCodeSuffixes": []
		},
		{
			"areaCode": "93",
			"displayMapping": {
				"zh-TW": "阿富汗",
				"en": "Afghanistan",
				"zh-CN": "阿富汗"
			},
			"countryCode": "AF",
			"mobileRegex": "^(\\+93){1}\\-\\d{6,11}",
			"areaCodeSuffixes": []
		}
	],
	"preferredAreaCode": "CN"
}
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

返回参数:

参数名 中文名称 类型 描述
preferredAreaCode 首选国际区号 String 当前企业中心配置的首选国际区号
countryCode 国家地区代码 String 国家地区代码
areaCode 国际电话区号 String 国际电话区号
areaCodeSuffixes 国际电话区号后缀 String 国际电话区号后缀
mobileRegex 手机号格式正则 String 手机号格式正则
displayMapping 多语言显示名映射 String 多语言显示名映射

# 内置滑动校验

在发送验证码时需要调用人机交互验证:


BlockPuzzleDialog mBlockPuzzleDialog = new BlockPuzzleDialog(mContext);
mBlockPuzzleDialog.setOnResultsListener(new OnResultsListener() {
        @Override
        public void onResultsClick(String result) {
            LogUtil.getInstance().d("二次校验回调结果 mCaptchaToken:" + result);
            //这个回调结果就是短信校验的captchaToken参数
        }
        @Override
        public void onError(String code, String msg) {
            ToastUtils.ShowToast(mContext, String.format("错误码 : %s  错误信息 : %s", code, msg));
        }
    });
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 用户名密码登录

AuthnCenterPW.Builder().userLoginRequest(this, name, pwd, new PWLoginListener<LoginRsp>() {
    @Override
    public void success(String code, LoginRsp rsp) {
        loginRsp = rsp;
        if (code.equals(SDKCodeType.SDK_SUCCESS.getCode())) {
            ToastUtils.ShowToast(MainActivity.this, "登录成功 返回数据为:" + rsp.getSession_token());
            return;
        }
        onNext(code); //根据返回值判断密码是否过期  参照返回CODE去判断     10006  密码已过期  ,  10007  密码即将过期  接入方可参考 DEMO   onNext方法
    }
    @Override
    public void error(String code, String t) {
        ToastUtils.ShowToast(MainActivity.this, "登录失败 返回数据为:" + t);
    }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 手机号密码登录

AuthnCenterPW.Builder().userLoginMobilePwd(this, name, pwd, new  PWLoginListener<LoginRsp>() {
    @Override
    public void success(String code, LoginRsp rsp) {
        loginRsp = rsp;
        if (code.equals(SDKCodeType.SDK_SUCCESS.getCode())) {
            ToastUtils.ShowToast(MainActivity.this, "登录成功 返回数据为:" + rsp.getSession_token());
            return;
        }
        onNext(code);
    }
    @Override
    public void error(String code, String t) {
        ToastUtils.ShowToast(MainActivity.this, "登录失败 返回数据为:" + t);
    }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 邮箱密码登录

AuthnCenterPW.Builder().userLoginEmailPwd(this, name, pwd, new PWLoginListener<LoginRsp>() {
    
    @Override
    public void success(String code, LoginRsp rsp) {
        loginRsp = rsp;
        if (code.equals(SDKCodeType.SDK_SUCCESS.getCode())) {
            ToastUtils.ShowToast(MainActivity.this, "登录成功 返回数据为:" + rsp.getSession_token());
            return;
        }
        onNext(code);
    }
    @Override
    public void error(String code, String t) {
        ToastUtils.ShowToast(MainActivity.this, "登录失败 返回数据为:" + t);
    }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 统一用户名密码登录

AuthnCenterPW.Builder().userLoginAuthRequest(this, name, pwd, new  PWLoginListener<LoginRsp>() {
    @Override
    public void success(String code, LoginRsp rsp) {
        loginRsp = rsp;
        if (code.equals(SDKCodeType.SDK_SUCCESS.getCode())) {
            ToastUtils.ShowToast(MainActivity.this, "登录成功 返回数据为:" + rsp.getSession_token());
            return;
        }
        onNext(code); //根据返回值判断密码是否过期  参照返回CODE去判断     10006  密码已过期  ,  10007  密码即将过期

    }
    @Override
    public void error(String code, String t) {
        ToastUtils.ShowToast(MainActivity.this, "登录失败 返回数据为:" + t);
    }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 跳过修改密码


AuthnCenterPW.Builder().skipPwd(MainActivity.this, loginRsp.getState_token(), new PWLoginListener<LoginRsp>() {
    @Override
    public void success(String code, LoginRsp rsp) {
        loginRsp = rsp;
        ToastUtils.ShowToast(MainActivity.this, "跳过修改成功 返回数据为:" + rsp.getSession_token());
    }
    @Override
    public void error(String code, String t) {
        ToastUtils.ShowToast(MainActivity.this, "跳过修改失败 返回数据为:" + t);
    }
});
1
2
3
4
5
6
7
8
9
10
11
12

# 强制修改密码

UpdatePwdReq up = new UpdatePwdReq();
up.setOld_password(oldPwd); 
up.setNew_password(newPwd);
AuthnCenterPW.Builder().updatePwd(MainActivity.this, up, loginRsp.getState_token(), new PWLoginListener<LoginRsp>() {
    @Override
    public void success(String code, LoginRsp rsp) {
        loginRsp = rsp;
        ToastUtils.ShowToast(MainActivity.this, "强制修改成功 返回数据为:" + rsp.getSession_token());
    }
    @Override
    public void error(String code, String t) {
        ToastUtils.ShowToast(MainActivity.this, "强制修改失败 返回数据为:" + t);
    }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 短信注册

UserInfoReq ur = new UserInfoReq();
ur.setUser_name(et_name.getText().toString().replace(" ", ""));
ur.setPwd(et_new_pwd.getText().toString().replace(" ", ""));
ur.setMobile(moblie);
ur.setVerify_code(verifyCode);
ur.setAttr_birthday(et_new_birthday.getText().toString().replace(" ", ""));
ur.setName("测试一");
ur.setAttr_nick_name("测试别名");
ur.setMailing_address("测试地址");
ur.setZip_code("430000");
ur.setAttr_gender(SexType.MALE.getSex()); //性别枚举
ur.setEmail("111@111.com");
ur.setFirst_name("测试First_name");
ur.setLast_name("测试Last_name");
ur.setIndustry("测试行业");
ur.setHead_img("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png");
TestExtensionBean tb = new TestExtensionBean();
tb.setAge(12);
ur.setExtension(tb);
AuthnCenterPW.Builder().userRegister(RegisterActivity.this, ur, new PWLoginListener<LoginRsp>() {
    @Override
    public void success(String code, LoginRsp rsp) {
        if (code.equals(SDKCodeType.SDK_SUCCESS.getCode()))
            ToastUtils.ShowToast(RegisterActivity.this, "注册成功: " + rsp.getSession_token());
    }
    @Override
    public void error(String code, String t) {
        ToastUtils.ShowToast(RegisterActivity.this, "注册失败: " + t);
    }
});
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
27
28
29
30

UserInfoReq 短信注册实体 相关字段解释:

参数名 中文名称 必须 类型 描述
user_name 用户名 String
name 姓名 String
mobile 手机号 String
verify_code 短信验证码 String
email 邮箱 String
pwd 密码 String
head_img 头像(url) String
attr_gender 性别 String 可选值有: female:女性; male:男性; unknow:保密
attr_birthday 生日 String 格式为: yyyy-MM-dd
attr_nick_name 昵称 String
mailing_address 邮寄地址 String
zip_code 邮政编码 String
first_name 名字 String
middle_name 中间名 String
last_name 姓氏 String
industry 所属行业 String
extension 扩展属性 JSONObject 扩展的属性需要在企业中定义

# 返回码

状态码 错误码 (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
访问控制身份验证源类型转换错误