本文正在参加「金石计划」
前言
短信验证码处理的实际应用:注册登陆界面获取验证码功能
- 获取验证码(限制60s):获取成功之后验证码输入框得到焦点,并开始计时器
- 格式校验
- 短信验证码的Checklist
I、实际应用的例子: 获取验证码(限制60s)
1.1 点击获取验证码处理
请求接口获取验证码,获取成功之后,开始到60S倒计时
- 监听点击事件,并处理获取成功之后的倒计时
UITapGestureRecognizer *cutTap = [[UITapGestureRecognizer alloc] init];
[[cutTap rac_gestureSignal] subscribeNext:^(id x) {
NSLog(@"获取验证码");
if(weakSelf.model.rightBtnblock){
// 参数为block
weakSelf.model.rightBtnblock(
^(id _Nonnull sender) {
// []
[self.textF becomeFirstResponder];
[self startCountdown];//test code
}// 参数
);
}
}];
[tmpView addGestureRecognizer:cutTap];
- 请求短信验证码:SendValidateCode
/** 本方法的参数类型时block,是获取完短信验证码的回调
,回调主要是执行60S倒计时
*/
- (void)SendValidateCode:(void (^)(id sender))tmp {
[QCTNetworkHelper Post:post parameters:params success:^(id _Nonnull responseObj) {
if(tmp){// 开始计时器
tmp(nil);
}
//
} failure:nil bizFailure:nil isShowLoadingDataGif:YES];
1.2、计时方法处理
- 去掉输入框的内容,短信验证码获取成功调用这个方法
#pragma mark - 计时方法, 去掉输入框的内容,短信验证码获取成功调用这个方法
//开始倒计时
- (void)startCountdown {
//
// //1\ 清空文本输入框
[self updateText:nil]; //
//
_textF.userInteractionEnabled = YES;
self.countdownTime = 60;
self.rightBtn.enabled = NO;
[self.rightBtn setTitle:[NSString stringWithFormat:@"%dS",self.countdownTime] forState:UIControlStateDisabled];
if (_timer) {
[_timer invalidate];
_timer = nil;
}
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}
//
//结束倒计时
- (void)stopCountdown {
if (_timer) {
[_timer invalidate];
_timer = nil;
}
[self.rightBtn setTitle:@"重新发送" forState:UIControlStateNormal];
// // self.renewBtn.userInteractionEnabled = YES;
self.rightBtn.enabled = YES;
self.rightBtn.layer.borderColor = RGB(255,83,85).CGColor;
[self.rightBtn setTitleColor:RGB(255,83,85) forState:UIControlStateNormal];
}
//
- (void)countdownAction:(NSTimer *)timer {
self.countdownTime --;
if (self.countdownTime < 0) {
self.countdownTime = 0;
[self stopCountdown];
} else {
[self.rightBtn setTitle:[NSString stringWithFormat:@"%dS",self.countdownTime] forState:UIControlStateDisabled];
}
}
//
//
//
//
//
- (NSTimer *)timer {
if (_timer == nil) {
_timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(countdownAction:) userInfo:nil repeats:YES];
}
return _timer;
}
II 格式正则校验
2.1 短信验证码格式正则校验
+ (BOOL)isSMSshouldChangeCharactersInRange:(NSString*)str{
//匹配以0开头的数字
//^\d{6}$"
// NSPredicate * predicate0 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",@"^[0][0-9]+$"];
//
NSPredicate * predicate1 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",@"^[0-9]{0,6}$"];
return [predicate1 evaluateWithObject:str] ? YES : NO;
}
2.2 金额校验格式正则校验
需求背景:商户进件新增、编辑、变更;费率设置支持到小数点后3位,如微信支付宝费率0.385;d0费率0.015
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSInteger len = range.length > 0?([textField.text length] - range.length): ([textField.text length] + [string length]);
if(len > 20){// 限制20位
return false;
}
NSMutableString * futureString = [NSMutableString stringWithString:textField.text];
if(range.length > 0){//允许删除
[futureString replaceCharactersInRange:range withString:string];
}else if(range.length<=0){
[futureString insertString:string atIndex:range.location];
}
if(futureString.length<1){//允许删除全部
return YES;
}
if(jjkFdTextF == textField){// 支持2位小数
return [QCT_Common isAmoutshouldChangeCharactersInRange:futureString.copy ];
}
//支持三位小数
return [QCT_Common isAmoutshouldChangeCharactersInRange3:futureString.copy];
}
支持三位小数
/**
前端商户费率填写支持三位小数
*/
+ (BOOL)isAmoutshouldChangeCharactersInRange3:(NSString*)str{
//匹配以0开头的数字
NSPredicate * predicate0 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",@"^[0][0-9]+$"];
//匹配两位小数、整数
NSPredicate * predicate1 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",@"^(([1-9]{1}[0-9]*|[0])\.?[0-9]{0,3})$"];
return ![predicate0 evaluateWithObject:str] && [predicate1 evaluateWithObject:str] ? YES : NO;
}
III、短信验证码的Checklist
- 一次一用
- 发送频率控制(建议60s获取一次)
- 验证码有效期(建议60s内有效,发短信时进行友好提示)
- 杂度(短信验证码建议6位数字)
- 安全提示:是否是个人自己操作等风险提示信息
- 在前端校验(客户端的校验只能作为辅助手段,很容易被绕过),必须使用服务端代码对输入数据进行最终校验
短信验证码需要限制频率使用
例如:每天一个手机号码只允许发送5次,防止被黑客恶意消耗短信
- 不同场景的短信验证码不可通用
- 单个短信验证码限制有效验证次数
- 验证码需要对应手机号不可通用