对读取短信验证码封装库的思考

简介: 在我的目前阶段,许多开源项目的产生都是直接来源于项目本身的需求,比如这次要讲的读取短信验证码的封装库。项目目前挂在 github 上的公司组织下,地址为:https://github.com/parkingwang/sms-captcha。

在我的目前阶段,许多开源项目的产生都是直接来源于项目本身的需求,比如这次要讲的读取短信验证码的封装库。

项目目前挂在 github 上的公司组织下,地址为:https://github.com/parkingwang/sms-captcha。使用方法很简单,在界面创建时注册:

mCaptchaObserver = SmsCaptcha.with(this)
        .captchaLength(4)
        .addressLike("10657%")
        .fillTo(mSmsCode)
        .createAndRegister();

界面销毁时移除注册:

mCaptchaObserver.unregister();

业务的实现

这里读取短信验证码的实现说来也很简单,核心逻辑就是动态注册一个短信的内容观察者,然后继承 ContentObserver,在收到回调之后查询指定号码的未读短信,通过正则过滤出验证码出来。最核心的代码如下:

do {
    // 获取短信内容
    final String body = cursor.getString(cursor.getColumnIndex(BODY));
    // 使用正则表达式匹配出验证码
    final Matcher matcher = mCaptchaPattern.matcher(body);
    if (!matcher.find() || matcher.groupCount() != 1) {
        // 匹配不出来则找下一条
        continue;
    }
    String code = matcher.group(1);
    if (TextUtils.isDigitsOnly(code)) {
        if (mCaptchaListener != null) {
            // 找到后回调并退出
            mCaptchaListener.onCaptchaReceived(code);
        }
        break;
    }
} while (cursor.moveToNext());

完整的代码可参考项目:https://github.com/parkingwang/sms-captcha。全部代码也很简单,目前就两个类,加一起也就两百多行。

封装的思考

在做好了之后,我就想到如何把它造成一个通用的轮子,以便可以在其他项目中使用。

验证码的正则表达式

首先,从内容中匹配出验证码,最简单有效的就是使用正则表达式了,所以,接下来的思考就是如何设计拼接出尽可能通用的正则表达式。
应用的验证码的文本格式通常按顺序包含如下信息:
包含应用名称的信息,“验证码”这三个字,连续的多位数字,其他内容。
需要注意的是,在这个“其他内容”中,也可能会包含多位数字,比如像这样的:如有疑问,请拨打客服电话xxx-xxxxxxxx。像这样的信息,如果你的正则表达式是如下这样的:

.*应用名称.*验证码.*\d{4}.*

由于正则表达式默认是贪婪模式,那么它就会匹配到后面的电话号码中的数字。所以需要使验证码这三个字与数字之间的搜索为懒惰模式,即加上问号,改为如下:

.*应用名称.*验证码.*?\d{4}.*

这种情况是确实存在的。当你是为一个项目写代码时,可以不考虑。但是当你是想做一个 SDK 给多个项目使用时,却应当尽可能地考虑存在的情况。尽可能的考虑严谨、周全。

另外,如果验证码的位数不固定,可能是 4-6 位之间,则匹配则为 \d{4,6},则如果都是4位,也可以写为 \d{4,4}

短信的查询条件

注册了短信的内容观察者之后,会在短信内容会变化时回调,然后在收到回调之后,我们就需要按照条件去查询符合结果的短信,并检索出内容里包含的验证码。这里的查询条件也简单说一下。
首先,要查询的短信验证码必须是未读的,因为已读的短信可能是过去已经使用的,对我们没有任何意义。
其次,有些应用的验证验证码的发送号码可能不是固定的,比如更换了短信服务端,所以应允许发送号码的模糊查询,可以查询以什么开头的号码。所以查询条件应该可以指定为:

address=xxxxxx AND read=0

address LIKE %xxxxx AND read=0

这两种模式。

剩下的封装工作就都比较简单,就不足一谈了。

对产品的思考

当你把代码实现之后,跑到手上的华为测试机,可能会发现,什么效果都没有。是代码出问题了吗?
再细查,会发现查询短信的时候,都没有查询出手机接收到的那条验证码短信,然后再试图扩大查询范围,发现手机里凡是涉及到验证码的短信都查询不出来。
各种尝试无果之后,你点开了短信里的“设置”,发现有个“高级”,点进去之后看到了一个“验证码安全保护”的功能,底下有一行小字“禁止第三方应用读取和使用验证码信息”的描述,这个功能是打开的状态。你恍然大悟,把它给关掉,再一试,果然验证码出来了。

但是这个功能是手机厂商默认打开的,而功能这么隐蔽,用户一般是不会去关闭的,那么怎么解决这个问题呢?
获取短信验证码的方法必然存在多种。之前负责对应项目的前同事,在获取不到验证码之后并没有细究原因,而是转向了另一种获取验证码的方式——通过截取通知栏的内容,从中获取验证码。

然而这种方式,它首先需要让用户授权应用读取通知栏内容的权限。这是一个很隐蔽也很敏感的权限,一旦你同意了,就意味着这个应用可以读取到所有应用发送到通知栏上的内容。而且打开了这个权限之后,用户自己很难再找到这个授权的地方去关闭它,所以它会是一个引起一些敏感用户不适的一个坑。

是不是要采取这种方式,我们回归到读取验证码本身这条产品需求上。
关于程序员对产品的思考,在去年与一个厦门的朋友聊天时,很同意他的一些观点。程序员需要有产品思维,需要有自己对产品的思考,去思考它的出发点。没有一点产品思维的话,以后的提升空间是有限的。
回到原来的话题上。这条需求是为了自动填充验证码,减少用户的输入,从而提升用户体验。
那么,为了实现这一点,而去要求用户去打开一个可能有些用户觉得特别敏感的权限,并且事后用户自己很难去关闭它,是提升了用户体验还是存在着损害用户体验或引起敏感用户对应用安全的不适感的风险呢?要知道,即便是支付宝或微信,用户都会怀疑其是否窃听、偷调摄像头、分析聊天内容,更不用说我们这种目前用户级别很小的应用了。

另一方面,自动填充验证码,这其实是一个可选的需求。换句话说,即便不能读取到验证码帮用户输入,用户也不会因此而觉得应用存在问题,可能许多用户甚至都不会想到这个问题。所以应避免把它给做得太重,从而舍本逐末。

目录
相关文章
方法:如何一次性把大量号码一键导入手机通讯录?
第一步:一堆大量号码一键导入手机通讯录,需要借助软件,金芝号码提取导入助手。第二步:在电脑上打开你的表格,里面的大量号码你先复制好,如果有对应的铭字你也复制好,然后分别粘贴进前面说的软件,接着你点软件上的“通讯录转换”,就可以得到一个通讯录文件。第三步:你从电脑上把这个文件发给你的手机,在手机上打开,就可以一键批量把大量号码导入通讯录。电脑文件怎么发送给手机,这个很容易呀,你的电脑上不是有电脑Q或者电脑微吗?发给你的手机微或者手机q就ok了,多方便!
方法:如何一次性把大量号码一键导入手机通讯录?
|
安全 Java API
阿里云——Java实现手机短信验证码功能
通过手机短信发送验证码,是最普遍、最安全验证用户真实身份的方式。目前,短信验证码广泛应用于用户注册、密码找回、登录保护、身份认证、随机密码、交易确认等应用场景。本文通过调用API开发一个短信验证码为例,带您了解如何实现短信验证码功能。
5643 5
阿里云——Java实现手机短信验证码功能
|
9月前
微信录音上传至七牛云控制器代码
微信录音上传至七牛云控制器代码
59 0
|
4月前
|
存储 小程序 关系型数据库
后台交互-个人中心->小程序登录微信登录接口演示,小程序授权登录理论,小程序授权登录代码演示,微信表情包存储问题
后台交互-个人中心->小程序登录微信登录接口演示,小程序授权登录理论,小程序授权登录代码演示,微信表情包存储问题
57 0
|
7月前
|
移动开发
微信h5扫码接口范例:使用localStorage防止扫码后表单其他内容丢失
微信h5扫码接口范例:使用localStorage防止扫码后表单其他内容丢失
73 0
|
8月前
|
存储 前端开发 NoSQL
TienChin 验证码响应结果分析&验证码生成接口分析
首先从前端开始进行分析,进入到登录页面,打开开发者工具(f12),找到 network,f5 刷新一下页面,然后,筛选一下,筛选内容为 Fetch/XHR:
61 0
TienChin 验证码响应结果分析&验证码生成接口分析
|
11月前
|
小程序 JavaScript
借助云开发10行代码实现短信验证码的发送
借助云开发10行代码实现短信验证码的发送
|
11月前
|
小程序 JavaScript 开发者
小程序短信验证码登录,1分钟实现小程序发短信功能,借助云开发10行代码实现短信验证码登录小程序
小程序短信验证码登录,1分钟实现小程序发短信功能,借助云开发10行代码实现短信验证码登录小程序
514 0
|
前端开发 数据库
eggjs 怎么实现更新用户信息接口去更新上传头像信息?
eggjs 怎么实现更新用户信息接口去更新上传头像信息?
120 0
 eggjs 怎么实现更新用户信息接口去更新上传头像信息?
|
物联网 开发者
演示读取TypeA TypeB nfc卡号|学习笔记
快速学习演示读取TypeA TypeB nfc卡号
486 0
演示读取TypeA TypeB nfc卡号|学习笔记

热门文章

最新文章