1.容联云官网
- 容联云通讯网址:https://www.yuntongxun.com/
- 注册并登陆
2、登录后,主控台
3、容联云创建应用
4、创建应用
5、填写应用信息
6、认证1
7、认证2
8、认证3
9、添加测试号
10、模板信息
注意:没上线,可以跳过认证那几步。
1.模板短信SDK下载
2.模板短信SDK使用说明
3.集成模板短信SDK
ccp_sms.py
文件中(修改4个地方)# -*- coding:utf-8 -*-
from verifications.libs.yuntongxun.CCPRestSDK import REST
# 说明:主账号,登陆云通讯网站后,可在"控制台-应用"中看到开发者主账号ACCOUNT SID
_accountSid = ''
# 说明:主账号Token,登陆云通讯网站后,可在控制台-应用中看到开发者主账号AUTH TOKEN
_accountToken = ''
# 请使用管理控制台首页的APPID或自己创建应用的APPID
_appId = ''
# 说明:请求地址,生产环境配置成app.cloopen.com
_serverIP = 'sandboxapp.cloopen.com'
# 说明:请求端口 ,生产环境为8883
_serverPort = "8883"
# 说明:REST API版本号保持不变
_softVersion = '2013-12-26'
# 云通讯官方提供的发送短信代码实例
# 发送模板短信
# @param to 手机号码
# @param datas 内容数据 格式为数组 例如:{'12','34'},如不需替换请填 ''
# @param $tempId 模板Id
def sendTemplateSMS(to, datas, tempId):
# 初始化REST SDK
rest = REST(_serverIP, _serverPort, _softVersion)
rest.setAccount(_accountSid, _accountToken)
rest.setAppId(_appId)
result = rest.sendTemplateSMS(to, datas, tempId)
print(result)
for k, v in result.items():
if k == 'templateSMS':
for k, s in v.items():
print('%s:%s' % (k, s))
else:
print('%s:%s' % (k, v))
if __name__ == '__main__':
# 注意: 测试的短信模板编号为1
sendTemplateSMS('已注册的测试手机号', ['123456', 5], 1) #注意 前面手机号,必须你你设置的测试号
if __name__ == '__main__':
# 注意: 测试的短信模板编号为1
sendTemplateSMS('已注册的测试手机号', ['123456', 5], 1) #注意 前面手机号,必须你你设置的测试号
5.模板短信SDK返回结果说明**
{
'statusCode': '000000', // 状态码。'000000'表示成功,反之,失败
'templateSMS':
{
'smsMessageSid': 'b5768b09e5bc4a369ed35c444c13a1eb', // 短信唯一标识符
'dateCreated': '20190125185207' // 短信发送时间
}
}
python ../../manage.py startapp verifications
pip install pillow
4、在verifications的app中,新建urls.py文件
from django.urls import re_path
from users.views import *
urlpatterns = [
]
5、项目总路由中,添加verifications的子路由
urlpatterns = [
path('admin/', admin.site.urls),
# 总路由的正则为空,表示总路由不会匹配任何路径前缀,把完整的路径交给子路由匹配
re_path(r'', include('users.urls')),
re_path(r'', include('verifications.urls')),
]
7、准备Redis的2、3号库存储验证码数据,注意比较写法上哪些不同
"verify_code": {
# 存储验证码数据
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/2",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
},
"sms_code": {
# 存储验证码数据
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/3",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
},
注:云服务器上需开放redis配置,否则外网访问,看不到redis图片
vim /root/redis-stable/redis.conf (我当前虚拟机/etc/redis/redis.conf )
#注释bind
#bind 127.0.0.1
修改后,重启Redis服务器。
sudo /etc/init.d/redis_6379 stop
sudo /etc/init.d/redis_6379 start
views.py内容:
from django.views import View # 从django.views导入View
from aerf_mall.libs.captcha.captcha import captcha #导入第三方包captcha
from django_redis import get_redis_connection # 导入redis库
from django.http import HttpResponse # 导入HttpResponse给前端进行响应
# Create your views here.
import logging # 导入日记模块
logger = logging.getLogger('django')
# 图形验证码接口
class ImageCodeView(View):
def get(self, request, uuid):
# 1、调用库生成图形验证码
text, image = captcha.generate_captcha()
# 2、存储redis
conn = get_redis_connection('verify_code')
try:
# 验证码写入redis
conn.setex(
"img_%s"%uuid,
300,
text
)
except Exception as e:
print(e)
logger.error(e)
# 3、构建响应
return HttpResponse(image, content_type='image/jpg')
9、根据项目文档要求,在verifications的app中的urls.py中写图片验证码接口
from django.urls import re_path # 从django.urls导入re_path
from . import views # 从当前文件夹,导入views
urlpatterns = [
# 图形验证码
re_path(r'^image_codes/(?P[\w-]+)/$' , views.ImageCodeView.as_view()),
]
http://127.0.0.1/register.html
测试Redis数据库:17307114007
redis-cli
select 2
keys *
get img_45c2f9f0-d382-4da4-aa6c-ce33db0b8712
1、请求方式:get
2、获取用户网页输入的内容:‘image_code’、‘image_code_id’ (request.GET.get())
3、校验参数:a、是否都有数据?b、校验验证码数据长度和格式(4位,正则re) c、校验uuid格式
4、校验用户输入的图形验证码,与Redis数据库中的是否一致。
get_redis_connection('verify_code')
.get("img_%s"%uuid)
5、如果没从Redis读到数据,向前端提示“验证码过期”
6、读到数据,用.decode()解码,删除原始数据:conn.delete(“img_%s”%uuid)
7、比对(忽略大小写)image_code.lower() != image_code_from_redis.lower():
8、发送短息要花钱的,如果上面校验没问题,才开始准备发送短信验证码
a)连接Redis的’sms_code’库,
b)检查60秒内,是否给同一个手机号,发送过短信
9、调用容联云发送短信接口。
10、向前端返回“成功”状态码
Redis的 C - S 架构:
存在的问题:
解决的办法:
管道pipeline
- 可以一次性发送多条命令并在执行完后一次性将结果返回。
- pipeline通过减少客户端与Redis的通信次数来实现降低往返延时时间。
实现的原理
- 实现的原理是队列。
- Client可以将三个命令放到一个tcp报文一起发送。
- Server则可以将三条命令的处理结果放到一个tcp报文返回。
- 队列是先进先出,这样就保证数据的顺序性。
1.实现步骤
1. 创建Redis管道2. 将Redis请求添加到队列3. 执行请求
2.代码实现
# 创建Redis管道
pl = redis_conn.pipeline()
# 将Redis请求添加到队列
pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
pl.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
# 执行请求
pl.execute()
views.py
from django.http import HttpResponse,JsonResponse
from aerf_mall.libs.yuntongxun.ccp_sms import CCP
import random # 注意如果使用快速导包,可能回出现 from random import random 代码会报错,要注意
import re
# 短信验证码接口
class SMSCodeView(View):
def get(self, request, mobile):
# 1、提取参数
image_code = request.GET.get('image_code')
uuid = request.GET.get('image_code_id')
# 2、校验参数
if not all([image_code, uuid]):
return JsonResponse({
'code': 400,
'errmsg': '缺少必要参数'
}, status=400)
if not re.match(r'^\w{4}$', image_code):
return JsonResponse({
'code': 400,
'errmsg': '图片验证码格式不符'
}, status=400)
if not re.match(r'^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$', uuid):
return JsonResponse({
'code': 400,
'errmsg': 'uuid格式不符'
}, status=400)
# 3、校验redis中的图片验证码是否一致——业务层面上的校验
conn = get_redis_connection('verify_code')
# 3.1 提取redis中存储的图片验证码
# get(): b"YBCF"
image_code_from_redis = conn.get("img_%s"%uuid)
# 如果从redis中读出的验证码是空;
if not image_code_from_redis:
return JsonResponse({
'code':400, 'errmsg': '验证码过期'}, status=400)
# 如果读出来的不是空,我们要删除该验证码
image_code_from_redis = image_code_from_redis.decode()
conn.delete("img_%s"%uuid)
# 3.2 比对(忽略大小写)
if image_code.lower() != image_code_from_redis.lower():
return JsonResponse({
'code': 400,
'errmsg': '图形验证码输入错误'
}, status=400)
# 4、发送短信验证码
conn = get_redis_connection('sms_code')
# 判断60秒之内,是否发送过短信——判断标志信息是否存在
flag = conn.get('flag_%s'%mobile)
if flag:
return JsonResponse({
'code':400, 'errmsg':'请勿重复发送短信'}, status=400)
# 构建6位手机验证码
sms_code = "%06d"%random.randint(0, 999999)
print("手机验证码:", sms_code)
# 生成一个redis的pipeline对象
p = conn.pipeline()
# 把验证码存入redis
p.setex(
"sms_%s"%mobile,
300,
sms_code
)
# 一旦用户发送了短信,需要在redis中存储一个标志
p.setex(
"flag_%s"%mobile,
60,
'1'
)
p.execute() # 批量执行队列中的指令
# 发送验证码
# 同步调用——只有当该发送短信当函数执行完毕,且返回了;代码才会继续往后执行!
# 如果网络出现了问题,该函数就会一致阻塞在此,导致我们的视图函数无法即使响应!
CCP().send_template_sms(mobile, [sms_code, 5], 1)
return JsonResponse({
'code': 0,
'errmsg': 'ok'
})
urls.py
# 获取短信验证码的子路由:
re_path(r'^sms_codes/(?P1[3-9]\d{9})/$' , views.SMSCodeView.as_view()),
测试Redis数据库:
redis-cli
select 3
keys *
get sms_13939396666