我们现在开发app,注册用户的时候,不再像web一样,发送到个人邮箱了,毕竟个人邮箱在移动端填写验证都很麻烦,一般都采用短信验证码的方式。今天我们就讲讲这方面的内容。

  首先,先找一个平台吧。我们公司找的容联云通讯这个平台,至少目前为止,用的还可以。先在容联上注册一下,然后创建一个应用,如下图所示:

  我只勾选了2个功能,他们这边还有很多其他功能,暂时用不到,就不选了。好了,点击"确认",一个应用就弄好了,下面就尝试着写代码发短信吧。

  容联为开发者提供了免费测试功能,但一个号码基本不会超过3次,所以用的时候要小心哦!容联的文档可能写的有点复杂了,反正我觉得稍微有点复杂,其实就是post一个request,我们把它提炼一下,得到下面这些代码。

 1 # coding:utf-8
 2 import datetime
 3 import hashlib
 4 import requests
 5 import json
 6 import base64
 7
 8
 9 def message_validate(phone_number, validate_number):
10     accountSid = "×××××××××"
11     accountToken = "×××××××××"
12     appid = "××××××××××"
13     templateId = '1'
14     now = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
15     signature = accountSid + accountToken + now
16     m = hashlib.md5()
17     m.update(signature)
18     sigParameter = m.hexdigest().upper()
19     # sigParameter = hashlib.md5().update(signature).hexdigest().upper()
20     url = "https://sandboxapp.cloopen.com:8883/2013-12-26/Accounts/%s/SMS/TemplateSMS?sig=%s" % (accountSid, sigParameter)
21     authorization = accountSid + ':' + now
22     new_authorization = base64.encodestring(authorization).strip()
23     headers = {'content-type': 'application/json;charset=utf-8', 'accept': 'application/json',
24                'Authorization': new_authorization}
25     data = {'to': phone_number, 'appId': appid, 'templateId': templateId, 'datas': [str(validate_number), '3']}
26     response = requests.post(url=url, data=json.dumps(data), headers=headers)
27     if response.json()['statusCode'] == '000000':
28         return True, response.json().get('statusMsg')
29     else:
30         return False, response.json().get('statusMsg')
31
32 if __name__ == '__main__':
33     result, reason = message_validate('137×××××××', '123456')
34     if result:
35         print '发送成功'
36     else:
37         print '发送失败'
38         print '原因是:' + reason.encode('utf-8')

看,这就是重新编辑的函数,是不是很简单,逐行分析一下吧。

首先, accountSid和accountToken 其实就相当于账户的用户名和密码,主要在这个页面可以看到。

其次,appid就是应用的appid,直接填进去就可以

至于templateId,其实就是你添加新的模板的id号,我们这边用开发者账号,直接填写'1'就可以了。

好了, 下面的代码,只要熟悉http的人,都会非常熟悉,基本都是把账号的id和token加上时间戳,转换成md5值,然后再encode一下,变成http的基本验证。判别有没有成功,按官网返回的参数,直接解析一下,是'000000'就代表成功,否则失败。

是不是很简单?就是这么简单,好了,既然发送短信的函数写好了,下面就写注册api接口吧。

一般的移动注册api接口可以分为3步

1、提交电话号码,发送短信验证,

2、验证短信

3、密码提交,

4、基本资料提交

一共4个接口,就register 1 2 3 4 吧,具体代码如下:

  1 @app.route('/register-step-1', methods=['POST'])
  2 def register_step_1():
  3     """
  4     接受phone_number,发送短信
  5     """
  6     phone_number = request.get_json().get('phone_number')
  7     user = User.query.filter_by(phone_number=phone_number).first()
  8
  9     if user:
 10         return jsonify({'code': 0, 'message': '该用户已经存在,注册失败'})
 11     validate_number = str(random.randint(100000, 1000000))
 12     result, err_message = message_validate(phone_number, validate_number)
 13
 14     if not result:
 15         return jsonify({'code': 0, 'message': err_message})
 16
 17     pipeline = redis_store.pipeline()
 18     pipeline.set('validate:%s' % phone_number, validate_number)
 19     pipeline.expire('validate:%s' % phone_number, 60)
 20     pipeline.execute()
 21
 22     return jsonify({'code': 1, 'message': '发送成功'})
 23
 24
 25 @app.route('/register-step-2', methods=['POST'])
 26 def register_step_2():
 27     """
 28     验证短信接口
 29     """
 30     phone_number = request.get_json().get('phone_number')
 31     validate_number = request.get_json().get('validate_number')
 32     validate_number_in_redis = redis_store.get('validate:%s' % phone_number)
 33
 34     if validate_number != validate_number_in_redis:
 35         return jsonify({'code': 0, 'message': '验证没有通过'})
 36
 37     pipe_line = redis_store.pipeline()
 38     pipe_line.set('is_validate:%s' % phone_number, '1')
 39     pipe_line.expire('is_validate:%s' % phone_number, 120)
 40     pipe_line.execute()
 41
 42     return jsonify({'code': 1, 'message': '短信验证通过'})
 43
 44
 45 @app.route('/register-step-3', methods=['POST'])
 46 def register_step_3():
 47     """
 48     密码提交
 49     """
 50     phone_number = request.get_json().get('phone_number')
 51     password = request.get_json().get('password')
 52     password_confirm = request.get_json().get('password_confirm')
 53
 54     if len(password) < 7 or len(password) > 30:
 55         # 这边可以自己拓展条件
 56         return jsonify({'code': 0, 'message': '密码长度不符合要求'})
 57
 58     if password != password_confirm:
 59         return jsonify({'code': 0, 'message': '密码和密码确认不一致'})
 60
 61     is_validate = redis_store.get('is_validate:%s' % phone_number)
 62
 63     if is_validate != '1':
 64         return jsonify({'code': 0, 'message': '验证码没有通过'})
 65
 66     pipeline = redis_store.pipeline()
 67     pipeline.hset('register:%s' % phone_number, 'password', password)
 68     pipeline.expire('register:%s' % phone_number, 120)
 69     pipeline.execute()
 70
 71     return jsonify({'code': 1, 'message': '提交密码成功'})
 72
 73
 74 @app.route('/register-step-4', methods=['POST'])
 75 def register_step_4():
 76     """
 77     基本资料提交
 78     """
 79     phone_number = request.get_json().get('phone_number')
 80     nickname = request.get_json().get('nickname')
 81
 82     is_validate = redis_store.get('is_validate:%s' % phone_number)
 83
 84     if is_validate != '1':
 85         return jsonify({'code': 0, 'message': '验证码没有通过'})
 86
 87     password = redis_store.hget('register:%s' % phone_number, 'password')
 88
 89     new_user = User(phone_number=phone_number, password=password, nickname=nickname)
 90     db_session.add(new_user)
 91
 92     try:
 93         db_session.commit()
 94     except Exception as e:
 95         print e
 96         db_session.rollback()
 97         return jsonify({'code': 0, 'message': '注册失败'})
 98     finally:
 99         redis_store.delete('is_validate:%s' % phone_number)
100         redis_store.delete('register:%s' % phone_number)
101
102     return jsonify({'code': 1, 'message': '注册成功'})

看到上面register的4个步骤没有,这边要注意的是具体方法:

步骤1:提交手机号码,验证。这个很基础,就不用说了,重要的是,发送过短信之后,要把短信验证码存在redis里面,以便下一个接口调用;其次,这个存储过程,一定要用pipeline,还要设置一个超时删除。想一想,假设你的程序在注册的过程中,崩掉,或者你中断程序,最起码不要影响其他程序,如果没有超时值,会产生很多的垃圾值,并且你还很难注意到。

步骤2:从redis里找到之前存储的验证码,对比,成功就进入下一步。这边,我还设置了一个is_validate值,最主要是防止客户端同事在这步会出错,或者其他知道这个接口的人,直接用脚本访问后面的接口,这样会出现未知的错误。

步骤3:验证一下密码是否符合要求,然后看一下上一步设置的is_validate是否存在,上面说了,防止恶意用户直接访问下面的接口,然后保存password到一个redis的hash值。这边主要为了方便客户端同事,不然下一个接口还要重新上传password值,客户端同事一定会恼火的。

步骤4:提交基本资料,然后保存。这边最重要的是,不管注册成功失败,自己注意把redis里面的值清理干净。看看我上面的接口,所有这些临时注册值,都设置了一个超时值,超过时间,就清理掉。

整个过程就完成了,可以去验证一下结果了。(其实这里还有缺陷,假设在第二步,我知道你这个接口,写个小脚本,暴力破解你的验证码,很快就能拿到的。这边可以做个小改动,在redis里面加一个值,访问一次,则添加1,超过一定次数,就返回错误代码。很简单,这边就不深入了)

好了,客户端验证代码如下:

 1 # coding:utf-8
 2 import requests
 3 import json
 4 from qiniu import put_file
 5
 6
 7 class APITest(object):
 8     def __init__(self, base_url):
 9         self.base_url = base_url
10         self.headers = {}
11         self.token = None
12         self.qiniu_token = None
13         self.qiniu_key = None
14         self.qiniu_base_url = 'http://7xk6rc.com1.z0.glb.clouddn.com/'
15
16     def login(self, phone_number, password, path='/login'):
17         payload = {'phone_number': phone_number, 'password': password}
18         self.headers = {'content-type': 'application/json'}
19         response = requests.post(url=self.base_url + path, data=json.dumps(payload), headers=self.headers)
20         response_data = json.loads(response.content)
21         self.token = response_data.get('token')
22         return response_data
23
24     def user(self, path='/user'):
25         self.headers = {'token': self.token}
26         response = requests.get(url=self.base_url + path, headers=self.headers)
27         response_data = json.loads(response.content)
28         return response_data
29
30     def logout(self, path='/logout'):
31         self.headers = {'token': self.token}
32         response = requests.get(url=self.base_url + path, headers=self.headers)
33         response_data = json.loads(response.content)
34         return response_data
35
36     def get_qiniu_token(self, path='/get-qiniu-token'):
37         response = requests.get(url=self.base_url + path)
38         response_data = json.loads(response.content)
39         self.qiniu_token = response_data.get('token')
40         self.qiniu_key = response_data.get('key')
41         if self.qiniu_token and self.qiniu_key:
42             print '成功获取qiniu_token和qiniu_key,分别为%s和%s' % (self.qiniu_token.encode('utf-8'), self.qiniu_key.encode('utf-8'))
43             localfile = '/home/yudahai/PycharmProjects/blog01/app/my-test.png'
44             ret, info = put_file(self.qiniu_token, self.qiniu_key, localfile)
45             print info.status_code
46             if info.status_code == 200:
47                 print '上传成功'
48                 self.head_picture = self.qiniu_base_url + self.qiniu_key
49                 print '其url为:' + self.head_picture.encode('utf-8')
50             else:
51                 print '上传失败'
52         return response_data
53
54     def set_head_picture(self, path='/set-head-picture'):
55         payload = {'head_picture': self.head_picture}
56         self.headers = {'token': self.token, 'content-type': 'application/json'}
57         response = requests.post(url=self.base_url + path, data=json.dumps(payload), headers=self.headers)
58         response_data = json.loads(response.content)
59         print response_data.get('message')
60         return response_data
61
62     def register_step_1(self, phone_number, path='/register-step-1'):
63         payload = {'phone_number': phone_number}
64         self.headers = {'content-type': 'application/json'}
65         response = requests.post(url=self.base_url + path, data=json.dumps(payload), headers=self.headers)
66         response_data = json.loads(response.content)
67         print response_data.get('code')
68         return response_data
69
70     def register_step_2(self, phone_number, validate_number, path='/register-step-2'):
71         payload = {'phone_number': phone_number, 'validate_number': validate_number}
72         self.headers = {'content-type': 'application/json'}
73         response = requests.post(url=self.base_url + path, data=json.dumps(payload), headers=self.headers)
74         response_data = json.loads(response.content)
75         print response_data.get('code')
76         return response_data
77
78     def register_step_3(self, phone_number, password, password_confirm, path='/register-step-3'):
79         payload = {'phone_number': phone_number, 'password': password, 'password_confirm': password_confirm}
80         self.headers = {'content-type': 'application/json'}
81         response = requests.post(url=self.base_url + path, data=json.dumps(payload), headers=self.headers)
82         response_data = json.loads(response.content)
83         print response_data.get('code')
84         return response_data
85
86     def register_step_4(self, phone_number, nickname, path='/register-step-4'):
87         payload = {'phone_number': phone_number, 'nickname': nickname}
88         self.headers = {'content-type': 'application/json'}
89         response = requests.post(url=self.base_url + path, data=json.dumps(payload), headers=self.headers)
90         response_data = json.loads(response.content)
91         print response_data.get('code')
92         return response_data
93
94 if __name__ == '__main__':
95     api = APITest('http://127.0.0.1:5001')
96     api.login('13565208554', '123456')
97     api.get_qiniu_token()
98     api.set_head_picture()
99     api.logout()

在命令行下验证一下吧。

整个过程是不是很简单?基于redis的注册机制就写到这。

转载于:https://www.cnblogs.com/yueerwanwan0204/p/5460668.html

flask开发restful api系列(5)-短信验证码相关推荐

  1. vue安装Postcss_Flask和Vue.js构建全栈单页面web应用【通过Flask开发RESTful API】

    前言: 看了一些国外的关于介绍flask和vue的前后端分离的文章,但没看到比较通俗易懂,代码完善的,直到昨天看到一篇新出的文章,而且内容非常棒,所以翻译过来,供大家一起学习. 原文来自Develop ...

  2. 自动化软件测试 - 通过 Android Studio 开发 App 自动拦截读取短信验证码

        之前一期介绍了怎样通过 Python 的代码去获取短信验证码去进行软件测试,这一期将主要介绍 怎样 通过 Android Studio 开发 App 自动拦截读取短信验证码.     Andr ...

  3. Android开发之属于你的短信验证码(二)

    君子欲讷于言而敏于行.-<论语> 最近身体有点不适,才注意到身体真的是最重要的,以后不管我们有多忙,一定要按时休息,坚持跑步,锻炼身体,做些颈椎的操等等,不要让我们挣的钱拿来看病,大家一起 ...

  4. android短信验证码方案,Android开发之属于你的短信验证码(一)

    不飞则已,一飞冲天;不鸣则已,一鸣惊人---------司马迁 最近工作又有新需求,要求用户在注册的时候需要通过手机验证码,这样做的目的是防止用户通过一个邮箱来随便的注册,那么好,今天我们就 一起来学 ...

  5. 小程序短信验证码登录,1分钟实现小程序发短信功能,借助云开发10行代码实现短信验证码登录小程序

    老规矩先看效果图 普通短信 验证码短信 今天被云开发官方告知,云开发支持发短信功能了,然后就迫不及待的来尝下鲜. 进入官方文档一看,云开发给咱们开发者的福利还真不小. 不仅仅可以很方便的使用短信功能, ...

  6. Java调用腾讯云短信API实现发送短信验证码完整。(详细,内附工具类)

    此先声明,本博文并不是为了推销腾讯云短信产品. 只是因为腾讯云短信SDK的使用指南讲的不是很详细,觉得肯定有很多人像我一样被搞的一头雾水.所以专门发一篇关于使用短信接口的博文,为了记录,也为了帮助和我 ...

  7. php easysms,二次开发-如何在PHPEMS-发送短信验证码(以easy-sms为例)

    第一步: 下载安装 https://packagist.org/packages/overtrue/easy-sm composer require overtrue/easy-sms 第二步: 在m ...

  8. 二次开发-如何在PHPEMS-发送短信验证码(以easy-sms为例)

    为什么80%的码农都做不了架构师?>>>    第一步: 下载安装 https://packagist.org/packages/overtrue/easy-sm composer ...

  9. 程序君带你畅聊发送短信验证码

    现在不管是网站,还是app等互联网和移动互联网产品,绝大部分注册都是直接用手机号注册登录的,方式就是给手机发送短信验证码,然后把验证码填入,后台程序去匹配判断用户填入的验证码和发送的是否一致. 我最近 ...

最新文章

  1. 5m 云服务器2核4g_华为云服务器2核4G 5M 248一年
  2. IOS8的新特性:简洁易用的毛玻璃效果
  3. linux 压缩 解压zip 命令
  4. 怎么用vnc访问自己电脑,并且同时又是同一个会话?
  5. 2021云上架构与运维峰会12月10日线上开启,五大精彩看点不容错过
  6. LEGO EV3 通信开发者套件
  7. java exe jdk_javac.exe 和java.exe两个可执行程序放在JDK安装目录的( )目录下。_学小易找答案...
  8. 人人视频从 App Store 下架整改,并下线“快看”相关内容,网友:我追的剧怎么办?...
  9. 判断能否组成三角形(水题)
  10. struts2之chain的使用
  11. 在服务器应用虚拟化中发现价值
  12. C#程序设计实践教程pdf
  13. 计算机二级vb考试教材,2020年9月全国计算机二级易考套餐:二级VB考试题库+教材...
  14. 【数据可视化应用】绘制峰峦图(附R语言代码)
  15. 史密斯探测证实,BioFlash可检出空气中的SARS-CoV-2变异株,包括德尔塔和德尔塔+
  16. Python OpenCV学习笔记之:图像直方图均衡化
  17. 依赖注入框架-dragger2
  18. npm install安装报错 npm ERR! code Z_BUF_ERROR 问题解决
  19. MapReduce操作实例
  20. 关闭windows安全中心报警

热门文章

  1. 在 GridView 控件中添加一列复选框51
  2. ubuntu 13.10 Rhythmbox不能播放mp3 和中文乱码的问题
  3. 【android】如何让WebView对Video标签的支持更强力
  4. stm32cubeide ST-LINK_gdbserver _ZTINSt8ios_base7failureB5cxx11E libstdc++.so.6问题解决
  5. 06丨MongoDB基本操作
  6. 什么是python编程例子_案例详解:优化Python编程的4个妙招
  7. EMR集群安全认证和授权管理
  8. 基于Flink+ClickHouse构建实时游戏数据分析最佳实践
  9. 【计算机视觉】究竟谁能解决可解释性 AI?
  10. 一个游戏美术写给策划的快速入门(二)