用App生成验证码的方式取代手机短信验证码方式?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用App生成验证码的方式取代手机短信验证码方式?相关的知识,希望对你有一定的参考价值。

目前想做手机短信验证码的功能,但是发现似乎可以通过其它的方式来实现这个效果。
1、单独做一个App,功能就是生成验证码。且安装这个App时,会生成唯一一个序列号,用来绑定用户账号。
2、当用户需要输入验证码时,需要打开上述的App,得到一个验证码,然后输入,完成验证。
说明:
1)App可以在无网络或有网络的状态下使用,且没有任何影响。
2)App在不停的自动生成验证码。
3)生成的验证码具有有效期。

提问:针对于以上的流程,这个App(无网络或有网络)生成验证码是怎么与服务器端完成实时匹配的?

但是这样无法验证是否真实用户在注册操作APP,除非再加上绑定用户的手机号或邮箱,但这样对于验证用户身份就复杂了,体验不太好,所以现在需要验证用户身份的app大都用的是短信验证码方式或补充一个第三方登录方式。当然还有比如像“点验”校验本机号码,也是一种让用户免输验证码能够实现身份验证的方式。 参考技术A 你说的就是软令牌。比如通常我们见到的网银的令牌时硬件的,而这个软令牌是一个可以装在手机上的APP,工作原理一样,可能根据时间来产生一次性动态口令。

Django--短信验证码

目前市面上可以发送短信验证码的平台有很多,此项目中使用的容联云通讯进行短信验证码的发送。

首先,我们先来进行手机验证码的逻辑分析,

技术图片

 

 

 通过这张图片,我们基本确定了发送短信验证码的基本逻辑,并且在业务逻辑中,我们不能让短信验证码任务阻塞了响应结果,所以我们需要采用celery方式进行异步发送短信验证码且不会阻塞响应。

既然确定了,核心逻辑和解决方案,那么接下来我们就进行代码实现了。

定义相关视图

# 编写短信验证码视图
class SmsVerVerifications(View):
    def get(self, request, mobile):
        pass

配置相关路由

url(r^sms_codes/(?P<mobile>1[3-9]d{9})/$,views.SmsVerVerifications.as_view(),name=SMS)

创建celery程序

在项目中,创建一个celery包。

注意:

  celery是一个独立程序,他不属于Django程序。

编写celery程序入口

# celery启动文件
from celery import Celery


# 为celery使用django配置文件进行设置
import os
if not os.getenv(DJANGO_SETTINGS_MODULE):
    os.environ[DJANGO_SETTINGS_MODULE] = meiduo_mall.settings.dev

# 创建celery实例
celery_app = Celery(meiduo)

# 加载celery配置
celery_app.config_from_object(celery_tasks.config)

# 自动注册celery任务
celery_app.autodiscover_tasks([celery_tasks.sms_task])

加载 Celery 配置

在 celery_tasks 包中再添加一个 config.py 文件:

技术图片

 

 

 在这个文件中指定一下 消息队列( 中间人 )的位置:

# 如果使用 redis 作为中间人
# 需要这样配置:
broker_url=redis://127.0.0.1:6379/3



# 如果使用别的作为中间人, 例如使用 rabbitmq
# 则 rabbitmq 配置如下:
broker_url= amqp://用户名:密码@ip地址:5672

# 例如: 
# meihao: 在rabbitq中创建的用户名, 注意: 远端链接时不能使用guest账户.
# 123456: 在rabbitq中用户名对应的密码
# ip部分: 指的是当前rabbitq所在的电脑ip
# 5672: 是规定的端口号
broker_url = amqp://meihao:123456@172.16.238.128:5672

说明:

上面的配置, 选择一个即可, 我们这里使用的是 redis

如果以后进入公司, 使用的不是 redis 作为存储的中间人.

则可以像我下面设置的那样, 设置别的工具作为中间人, 例如: rabbitmq

 

我们还需要把 config 添加到刚刚创建的对象中:

在 celery_tasks.main.py 中, 额外增加如下代码:

from celery import Celery

celery_app = Celery(meiduo)

# 将刚刚的 config 配置给 celery
# 里面的参数为我们创建的 config 配置文件:
celery_app.config_from_object(celery_tasks.config)

定义任务

技术图片

注册任务:

我们需要在 celery_tasks 包下, 再创建一个包, 名字随意

例如, 我这里为 sms.

创建好后, 需要在里面添加一个 tasks.py 文件.

注意, 这里的 tasks 名字是规定死的.

然后需要在 celery_tasks.main.py 报备刚刚创建的文件:

from celery import Celery

celery_app = Celery(meiduo)

celery_app.config_from_object(celery_tasks.config)

# 让 celery_app 自动捕获目标地址下的任务: 
# 就是自动捕获 tasks
celery_app.autodiscover_tasks([celery_tasks.sms])
实现任务:

已经报备之后, 我们就可以在 tasks.py 中添加具体的内容了

在 celery_tasks.sms.tasks.py 文件中添加如下代码:

from celery_tasks.main import celery_app

@celery_app.task(name=ccp_send_sms_code)
def ccp_send_sms_code(mobile, sms_code):
    ‘‘‘该函数就是一个任务, 用于发送短信‘‘‘
    result = CCP().send_template_sms(mobile, 
                                     [sms_code, 5], 
                                     1)
    return result
调用任务

我们创建了一个任务, 现在就可以调用该任务了.

没有使用这个任务之前, 我们发送短信调用的代码写在了

verifications.views.py 中. 所以我们现在这个任务的调用还是

在那个位置, 用该任务替换以前发送短信的函数:

from celery_tasks.sms.tasks import ccp_send_sms_code

# 原来的写法:
# CCP().send_template_sms(mobile, [sms_code, 5], 1)

# 改为现在的写法, 注意: 这里的函数,调用的时候需要加: .delay()
ccp_send_sms_code.delay(mobile, sms_code)

则, 我们现在的发送短信接口变为了:

from celery_tasks.sms.tasks import ccp_send_sms_code

class SMSCodeView(View):
    def get(self, reqeust, mobile):
        redis_conn = get_redis_connection(verify_code)
        send_flag = redis_conn.get(send_flag_%s % mobile)
        if send_flag:
            return http.JsonResponse({code: 400,
                                      errmsg: 发送短信过于频繁})

        image_code_client = reqeust.GET.get(image_code)
        uuid = reqeust.GET.get(image_code_id)

        if not all([image_code_client, uuid]):
            return http.JsonResponse({code: 400,
                                      errmsg: 缺少必传参数})

        image_code_server = redis_conn.get(img_%s % uuid)
        if image_code_server is None:
            return http.JsonResponse({code: 400,
                                      errmsg: 图形验证码失效})

        try:
            redis_conn.delete(img_%s % uuid)
        except Exception as e:
            logger.error(e)

        image_code_server = image_code_server.decode()
        if image_code_client.lower() != image_code_server.lower():
            return http.JsonResponse({code: 400,
                                      errmsg: 输入图形验证码有误})

        sms_code = %06d % random.randint(0, 999999)
        logger.info(sms_code)

        pl = redis_conn.pipeline()
        pl.setex(sms_code_%s % mobile, 300, sms_code)
        pl.setex(send_flag_%s % mobile, 60, 1)
        pl.execute()


        # 原来的写法:
        # CCP().send_template_sms(mobile, [sms_code, 5], 1)

        # 改为现在的写法, 注意: 这里的函数,调用的时候需要加: .delay()
        ccp_send_sms_code.delay(mobile, sms_code)

        return http.JsonResponse({code: 0,
                                  errmsg: 发送短信成功})

启动消费者( celery充当 )

# 想要启动 celery 服务, 调用下面的命令行: 
cd ~/projects/meiduo_project/meiduo_mall

celery -A celery_tasks.main worker -l info

参数说明:

celery : 调用 celery 命令

-A : 作用是指定要启动的文件, 这个参数后面的文件会被执行.

worker : 启动的对象是 worker, 工人, 干活的人

-l : 指日志打印等级, 一般日志都是通知形式的, 即: info 级别

启动 worker 成功以后长啥样? 下图:

 

技术图片

 

 

 技术图片

 

 技术图片

 

以上是关于用App生成验证码的方式取代手机短信验证码方式?的主要内容,如果未能解决你的问题,请参考以下文章

图形验证码的两种实现方式

图形验证码的两种实现方式

Yii2在Form中处理短信验证码的Validator,耦合度最低的短信验证码验证方式

用Java redis 实现发送手机验证码的功能

哪位大神,短信接口使用的是阿里云的短信验证平台

Django--短信验证码