客户身份(CIAM)

短信登录

# 文档说明

本文为您介绍iOS客户端如何接入短信登录功能。短信登录功能,即向用户手机号发送短信验证码,用户凭借手机号和短信验证码到IDaaS服务端认证。

短信登录使用场景下,用户输入手机号,点击获取短信验证码按钮,拉起滑块校验,校验成功后,IDaaS后台发送短信验证码到此手机号。用户输入验证码,点击登录后,IDaaS后台认证,返回票据。最终认证结果返回给App。

# 流程说明

# 登录流程

集成流程说明

  1. 用户输入手机号,App客户端检查手机号是否符合格式规则。用户点击获取验证码。

  2. App客户端调用滑块验证方法,IDaaS SDK请求IDaaS后端滑块校验初始化信息,在页面展示滑块校验窗口。

  3. 用户拖动滑块,完成滑块校验,IDaaS SDK完成采集滑块校验信息,请求IDaaS服务端进行校验。

  4. IDaaS服务端完成滑块校验成功,返回token给IDaaS SDK。

  5. IDaaS SDK拿到token,用token请求IDaaS服务端发送短信。

  6. 用户接收到短信,填入验证码,点击登录。

  7. App客户端用手机号和验证码,调用IDaaS SDK的短信登录方法。

  8. IDaaS SDK 请求短信登录,IDaaS 服务端发起认证流程,认证成功返回session_token和id_token给IDaaS SDK;认证不成功返回错误码和信息给IDaaS SDK。

  9. IDaaS SDK拿到登录结果,返回给App客户端,App客户端通过结果进入app自己的流程。

  10. 客户端可以使用id_token来校验登录有效期和获取用户基本信息。

  11. 客户端可以使用session_token来刷新id_token。

# 环境搭建

# 获取应用clientID

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

# 引入依赖包

无第三方sdk依赖

# 添加主库

AuthnCenter_common_2C.framework	  
AuthnCenter_SMSLogin_2C.bundle
AuthnCenter_SMSLogin_2C.framework  
1
2
3

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

并且引入Pod的依赖包。

pod 'JWT', '~> 3.0.0-beta.14'

# Targets设置

  • IDaaS短信登录SDK最低版本可兼容ios 10。

  • 在framework, library,and embedded content里引入以下包。

  • Framework,Libraries,andEmbedded Content里添加主库和依赖包,且在Other Linker Flags增加-ObjC。

  • 在菜单栏选择TARGETS > Info > Custom iOS Target Properties > App Transport Security Settings > Allow Arbitrary Loads,如下图。

  • 配置bitcode,如下图,设置bitcode为NO。

# 开发集成

引入头文件:

在appdelegate中引用如下
#import <AuthnCenter_common_2C /BCIDACommonManager.h>
1
2

# SDK初始化

IDaaS SDK提供一个初始化方法,您可在初始化方法里填入租户,clientID和是否打开log日志打印。

初始化方法的示例:将初始化的方法在appdelegate 中的didFinishLaunchingWithOptions方法中初始化。

//1. 基本配置初始化
[[[[[BCIDACommonManager sharedInstance] initWithDomain:@"https://你的后台租户.com"] initWithClientID:@"后台租户clientID"] initWithSSLCerVerification:NO] setLogEnabled:YES] ;
1
2

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

/**
  * 函数名:sharedInstance
   * @param 无
   * @return 单例对象实例类
 */
+ (instancetype )sharedInstance ;

/**
  * 函数名:initWithDomain
   * @param domain,以https://开头,以.com结尾。
   * @return 实例类
 */
-(BCIDACommonManager)initWithDomain:(NSString)domain

/**
  * 函数名:initWithClientID
   * @param client id。
   * @return 实例类
 */
-(BCIDACommonManager)initWithClientID:(NSString)clientID;

/**
  * 函数名:setLogEnabled
   * @param 布尔值是否开启log。
   * @return 实例类
 */
-(void)setLogEnabled:(BOOL)enable;

/**
  * 函数名:initWithSSLCerVerification
   * @param 布尔值设置ssl证书是否开启检测。
   * @return 实例类
 */
-(BCIDACommonManager*)initWithSSLCerVerification:(bool)sslCerVerification;
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

# 调用顺序

  1. 如果开启了国际号码支持,请自行先行调用国际区号获取接口,进行界面绑定与展示并在需要传入手机号的方法上,自行组装国际区号(例如:+86-13800000000)传入即可;如未开启支持则忽略此接口。

  2. 调用滑块校验并发送短信 (startSlidingVerifyCodePageWithMobileNumber)入参手机号。

  3. 调用短信登录方法(loginsBySMSWithMobile)入参手机号 短信验证码。

# 发送短信验证

App客户端需要有自己的UI界面,界面包含几个必要组件:手机号输入框,验证码输入框,触发获取验证码的按钮(或者事件),登录的按钮(或者事件)。

  1. 在用户填入手机号码后,点击(触发)发送验证码事件之前,App客户端做手机号格式检查。

  2. 点击(触发)发送验证码事件,App客户端调用IDaaS SDK的发送验证码方法,示例如下:

//导入请求头
#import <AuthnCenter_SMSLogin_2C/BCSMSLoginSlideVerifyCodeManager.h>

//点击(触发)发送验证码事件
  [BCSMSLoginSlideVerifyCodeManager startSlidingVerifyCodePageWithMobileNumber:手机号 andWithResultHandler:^(NSString * _Nonnull code, id  _Nonnull data) {
            __strong __typeof(weakSelf)strongSelf = weakSelf;

            dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"滑块验证结果==%@==%@",code,data);
            
            });
        }];
1
2
3
4
5
6
7
8
9
10
11
12

BCSMSLoginSlideVerifyCodeManager对象方法简介:

/**
* 函数名:startSlidingVerifyCodePageWithMobileNumber
* @brief:点击拉起滑块验证,验证成功发送短信,滑块验证不成功返回code=错误码,data返回错误原因。发送短信成功code=0.
*@ param mobile手机号:带区号“+86-13800000000”或者不带区号“13800000000”都可以。
*@param complete:异步结果回调,code=0短信发送成功,code=其他 是短信发送失败或者滑块校验失败,请参照IDaaS 错误码和返回的data(字符串错误描述)。code=105 data=”用户关闭”是滑块框的关闭被点击了,滑块框被关闭。
**/
+(void)startSlidingVerifyCodePageWithMobileNumber:(NSString*)mobile andWithResultHandler:(BCSMSLoginSlideCodeHandlerBlock)resultHandler;
1
2
3
4
5
6
7

# 手机号和短信验证码登录

完成上一个验证码发送,用户收到短信验证码,填入验证码框,触发登录事件,此时App客户端调起短信登录流程,示例代码如下:

[[BCLoginSMSManager sharedInstance] loginsBySMSWithMobile:手机号 andWithVerifyCode:验证码 andWithCompletionHandler:^(NSString * _Nonnull code, id  _Nonnull data) {
        __strong __typeof(weakSelf)strongSelf = weakSelf;

        dispatch_async(dispatch_get_main_queue(), ^{
   //登录成功失败,跳转
        });
  }];
1
2
3
4
5
6
7

主类BCLoginSMSManager方法简介:

/**
* 函数名:loginsBySMSWithMobile
* @brief:短信登录方法
* @param mobile 手机号
*@param verifyCode 短信验证码
* @param BCLoginSMSCompleteHandler ()登录结果回调函数
**/
-(void) loginsBySMSWithMobile:(NSString*)mobile andWithVerifyCode:(NSString*)verifyCode andWithCompletionHandler:(BCLoginSMSCompleteHandler)completeHandler;
1
2
3
4
5
6
7
8

BCLoginSMSCompleteHandler回调函数返回码:

code码 说明
code=0 登录成功,此时data会返回NSDictionary: data=@{@"session_token":sessionToken内容,@"id_token":idToken内容};
code=1 登录失败,data返回字符串描述错误

# 手机国际区号获取

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

IDaaS SDK提供了获取国际区号的API:

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

#import <AuthnCenter_common_2C/BCIDAInternationalPhoneCodeManager.h>


[BCIDAInternationalPhoneCodeManager getInternaltionalAreaCodeWithCompletionHandler:^(NSString * _Nonnull code, id  _Nonnull data) {
        __strong __typeof(weakSelf)strongSelf = weakSelf;
        dispatch_async(dispatch_get_main_queue(), ^{
            NSDictionary* dic=(NSDictionary*)data;
        //判断电话是否符合正则表达式 
 BOOL flag=  [strongSelf parseDictionary:dic andWithMoile:mobile];
            
        });
    }];
1
2
3
4
5
6
7
8
9
10
11
12

主类方法介绍:

/**
* 函数名:getInternaltionalAreaCodeWithCompletionHandler
* @brief:获取国际区号方法
* @param 
*@param 
* @param BCSMSGetInternationalAreaCodeHandlerBlock ()结果回调函数 code=0,data返回NSDictionary的结果
**/
+(void)getInternaltionalAreaCodeWithCompletionHandler:(BCSMSGetInternationalAreaCodeHandlerBlock)resultHander;
1
2
3
4
5
6
7
8

成功示例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 多语言显示名映射

# IDToken校验和获取用户信息

在登录成功后会返回session_token和id_token。id_token可以用来获取用户信息和校验登录有效期。

  1. 校验idToken
  2. 从idtoken中获取用户信息(可以不通过校验直接调用此方法)

# 校验id_token

调用示例:

  [[BCIDAIDTokenManager sharedInstance] verifySignWithIdToken:idToken andWithCallBack:^(NSString * _Nonnull code, id  _Nonnull data) {
          }];
1
2

主类BCIDAIDTokenManager介绍:

/**
   * 函数名:sharedInstance
   * @param 无入参
   * @return返回对象单例实例
*/
+ (instancetype )sharedInstance;

/**
* 函数名:verifySignWithIdToken
* @brief:校验idtoken是否在登录有效期和应用一致的方法
* @param idToken登录时候返回的
* @param BCIDAIdTokenVerifyHandlerBlock回调函数:
NSString code
id       data
**/
-(void)verifySignWithIdToken:(NSString*)idToken andWithCallBack:(BCIDAIdTokenVerifyHandlerBlock)callback;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

返回值:

code(NSString) data data的数据类型和说明
0 success [NSString]验签成功
1 错误描述 [NSString]入参为空,sdk初始化参数domain和clientID没有设置
106 时间过期 [NSString]过期的idtoken
107 clientID不符合 [NSString]可能使用了其他应用的clientID
103 验签失败 [NSString]验签过程失败
102 获取公钥为空 [NSString]验签过程中错误
见文末错误码集合 见文末错误码集合 还可能返回文末的错误码

# 从idToken解析出用户信息

调用示例:

[[BCIDAIDTokenManager sharedInstance] getUserInfoFromIdTokenWithIdToken:idToken andWithCallBack:^(NSString * _Nonnull code, id  _Nonnull data) {
            
}];
1
2
3

主类BCIDAIDTokenManager介绍:

/**
   * 函数名:sharedInstance
   * @param 无入参
   * @return返回对象单例实例
*/
+ (instancetype )sharedInstance;

/**
* 函数名:getUserInfoFromIdTokenWithIdToken
* @brief:从idToken解析用户信息
* @param idToken登录返回的
* @param BCIDAIdTokenGetInfoHandlerBlock回调函数:
NSString code
id       data

**/
-(void)getUserInfoFromIdTokenWithIdToken:(NSString*)idToken andWithCallBack:(BCIDAIdTokenGetInfoHandlerBlock)callback;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

用户信息参数说明:

参数名 描述
iss 令牌签发人
aud 令牌接收者,应用的clientId
exp 令牌的过期时间
jti 令牌的id
iat 令牌的签发时间
sub 固定为subject
name 用户姓名
mobile 用户手机号
id 用户的id
userName 用户名
email 用户邮箱

回调函数返回值:

成功示例:
code=0
data=
{
	"id": "20220729174957176-2C7F-A2C54C293",
	"exp": 1659407592,
	"nbf": 1659407172,
	"mobile": "+86-13808603636",
	"jti": "7iwCYPo8EYcmLAD18x-CAw",
	"iss": "https:\/\/sdk2c.idaas-test-alpha.bccastle.com\/api\/v1\/oauth2",
	"userName": "zhangrui1",
	"sub": "20220729174957176-2C7F-A2C54C293",
	"aud": "S1ScicdIVR1QUbNs8TBz6BYVd2Zt8Adc",
	"iat": 1659407292,
	"email": "",
	"name": "zhangrui1"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 刷新IDToken

调用示例:

[[BCIDAIDTokenRefreshManager sharedInstance] refreshIdTokenWithSessionToken:sessionToken andWithCallBack:^(NSString * _Nonnull code, id  _Nonnull data) {
            NSString* jsonS=(NSString*)data;
         NSDictionary* dict=  [self dictionaryWithJsonString:jsonS];//解析jsonStr到NSDictionary
          NSString* idTok= [dict objectForKey:@"id_token"];
            NSString* session_tok=[dict objectForKey:@"session_token"];
            NSString* expr=[dict objectForKey:@"expire"];
                  }];
1
2
3
4
5
6
7

主类BCIDAIDTokenManager介绍:

/**
   * 函数名:sharedInstance
   * @param 无入参
   * @return返回对象单例实例
*/
+ (instancetype )sharedInstance;

/**
* 函数名:refreshIdTokenWithSessionToken
* @brief:刷新idToken
* @param sessionToken登录返回的
* @param BCIDAIdTokenRefreshIDTokenHandlerBlock回调函数:
NSString code
id       data

**/
-(void)refreshIdTokenWithSessionToken:(NSString*)sessionToken andWithCallBack:(BCIDAIdTokenRefreshIDTokenHandlerBlock)callBack;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

回调函数返回值:

成功示例:
code=0
data=
{
  "id_token" : "eyJraWQiOiJhODJkzJjLmlkYWFzLXRllKp6w",
  "session_token" : "apcOKuyry7kASh9h6mtf2G2GbettkyiU",
  "expire" : 7200
}

失败示例(获取不到数据)
code=1
1
2
3
4
5
6
7
8
9
10
11

# 返回码

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