短信登录
# 文档说明
本文为您介绍iOS客户端如何接入短信登录功能。短信登录功能,即向用户手机号发送短信验证码,用户凭借手机号和短信验证码到IDaaS服务端认证。
短信登录使用场景下,用户输入手机号,点击获取短信验证码按钮,拉起滑块校验,校验成功后,IDaaS后台发送短信验证码到此手机号。用户输入验证码,点击登录后,IDaaS后台认证,返回票据。最终认证结果返回给App。
# 流程说明
# 登录流程
集成流程说明
用户输入手机号,App客户端检查手机号是否符合格式规则。用户点击获取验证码。
App客户端调用滑块验证方法,IDaaS SDK请求IDaaS后端滑块校验初始化信息,在页面展示滑块校验窗口。
用户拖动滑块,完成滑块校验,IDaaS SDK完成采集滑块校验信息,请求IDaaS服务端进行校验。
IDaaS服务端完成滑块校验成功,返回token给IDaaS SDK。
IDaaS SDK拿到token,用token请求IDaaS服务端发送短信。
用户接收到短信,填入验证码,点击登录。
App客户端用手机号和验证码,调用IDaaS SDK的短信登录方法。
IDaaS SDK 请求短信登录,IDaaS 服务端发起认证流程,认证成功返回session_token和id_token给IDaaS SDK;认证不成功返回错误码和信息给IDaaS SDK。
IDaaS SDK拿到登录结果,返回给App客户端,App客户端通过结果进入app自己的流程。
客户端可以使用id_token来校验登录有效期和获取用户基本信息。
客户端可以使用session_token来刷新id_token。
# 环境搭建
# 获取应用clientID
登录IDaaS企业中心平台,点击 “资源-->应用” 选择跟自己相关的应用点击即可查看到。
# 引入依赖包
无第三方sdk依赖
# 添加主库
AuthnCenter_common_2C.framework
AuthnCenter_SMSLogin_2C.bundle
AuthnCenter_SMSLogin_2C.framework
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>
2
# SDK初始化
IDaaS SDK提供一个初始化方法,您可在初始化方法里填入租户,clientID和是否打开log日志打印。
初始化方法的示例:将初始化的方法在appdelegate 中的didFinishLaunchingWithOptions方法中初始化。
//1. 基本配置初始化
[[[[[BCIDACommonManager sharedInstance] initWithDomain:@"https://你的后台租户.com"] initWithClientID:@"后台租户clientID"] initWithSSLCerVerification:NO] setLogEnabled:YES] ;
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;
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
# 调用顺序
如果开启了国际号码支持,请自行先行调用国际区号获取接口,进行界面绑定与展示并在需要传入手机号的方法上,自行组装国际区号(例如:+86-13800000000)传入即可;如未开启支持则忽略此接口。
调用滑块校验并发送短信 (startSlidingVerifyCodePageWithMobileNumber)入参手机号。
调用短信登录方法(loginsBySMSWithMobile)入参手机号 短信验证码。
# 发送短信验证
App客户端需要有自己的UI界面,界面包含几个必要组件:手机号输入框,验证码输入框,触发获取验证码的按钮(或者事件),登录的按钮(或者事件)。
在用户填入手机号码后,点击(触发)发送验证码事件之前,App客户端做手机号格式检查。
点击(触发)发送验证码事件,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);
});
}];
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;
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(), ^{
//登录成功失败,跳转
});
}];
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;
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];
});
}];
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;
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"
}
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可以用来获取用户信息和校验登录有效期。
- 校验idToken
- 从idtoken中获取用户信息(可以不通过校验直接调用此方法)
# 校验id_token
调用示例:
[[BCIDAIDTokenManager sharedInstance] verifySignWithIdToken:idToken andWithCallBack:^(NSString * _Nonnull code, id _Nonnull data) {
}];
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;
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) {
}];
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;
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 | 用户名 |
用户邮箱 |
回调函数返回值:
成功示例:
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"
}
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"];
}];
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;
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
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 | |
访问控制身份验证源类型转换错误 |