开发者社区> 浩码农> 正文

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

简介: 在我的目前阶段,许多开源项目的产生都是直接来源于项目本身的需求,比如这次要讲的读取短信验证码的封装库。 项目目前挂在 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

这两种模式。

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

对产品的思考

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

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

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

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

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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
如何设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云安全组设置详细图文教程(收藏起来) 阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程。阿里云会要求客户设置安全组,如果不设置,阿里云会指定默认的安全组。那么,这个安全组是什么呢?顾名思义,就是为了服务器安全设置的。安全组其实就是一个虚拟的防火墙,可以让用户从端口、IP的维度来筛选对应服务器的访问者,从而形成一个云上的安全域。
17037 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,大概有三种登录方式:
9087 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
24808 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,云吞铺子总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系统盘、创建快照、配置安全组等操作如何登录ECS云服务器控制台? 1、先登录到阿里云ECS服务器控制台 2、点击顶部的“控制台” 3、通过左侧栏,切换到“云服务器ECS”即可,如下图所示 通过ECS控制台的远程连接来登录到云服务器 阿里云ECS云服务器自带远程连接功能,使用该功能可以登录到云服务器,简单且方便,如下图:点击“远程连接”,第一次连接会自动生成6位数字密码,输入密码即可登录到云服务器上。
32762 0
使用SSH远程登录阿里云ECS服务器
远程连接服务器以及配置环境
12491 0
阿里云服务器ECS登录用户名是什么?系统不同默认账号也不同
阿里云服务器Windows系统默认用户名administrator,Linux镜像服务器用户名root
13823 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
14683 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
17998 0
+关注
浩码农
开源社区技术专家
222
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载