一:准备工作:
1:将yuntongxun包,放在verifications/libs下面。
2:修改云通讯下的ccp_sms.py文件
_accountSid = '8a216da873cec13201744db8f'
# 说明:主账号Token,登陆云通讯网站后,可在控制台-应用中看到开发者主账号AUTH TOKEN
_accountToken = 'e6128f3209c843cabe6576'
# 请使用管理控制台首页的APPID或自己创建应用的APPID
_appId = '8a216da873cec13201744db'
二 :写视图函数:
class SMSCodeView(View):
# 1:提取参数,用户输入的图片验证码,图片的uuid。
# 2:校验参数
# 存在性校验
# 格式校验
# 匹配校验---用户输入的图片验证码和redis存在的验证码是否相同。
# 3:数据处理---利用云通讯给用户发送验证码
# 生成随机6位数的验证码
# 将验证码写入数据库
# 利用云通讯发送验证码
# 4:构建响应
class SMSCodeView(View):
def get(self, request, mobile):
# 1、提取参数
image_code = request.GET.get('image_code')
uuid = request.GET.get('image_code_id')
# 2、校验参数
# 2.1、参数必要性校验
if not all([image_code, uuid]):
return JsonResponse({
'code': 400,
'errmsg': '参数缺失'
}, status=400)
# 2.2、校验image_code
if not re.match(r'^[a-zA-Z0-9]{4}$', image_code):
return JsonResponse({
'code': 400,
'errmsg': '图形验证码格式有误!'
}, status=400)
# 2.3、校验图片验证码的uuid
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)
解释: image_code = request.GET.get(‘image_code’)
uuid = request.GET.get(‘image_code_id’)
提取查询字符串参数,一个是用户输入的验证码,一个是图片的UUID。
2.1表示UUID和用户输入的验证码是必传项。
2.3表示UUID符合UUID的格式
# 2.4、校验用户输入的图形验证码和redis中记录的是否一致
# 2.4.1、根据uuid提取redis中的图形验证码
conn = get_redis_connection('verify_code')
# 过期:None;
# 存在:b'ABCD' ---> 'ABCD'
image_code_from_redis = conn.get('img_%s'%uuid)
# 图片验证码:读一次,删一次,保证该图片验证码只会被使用"一次"!
conn.delete('img_%s'%uuid)
if not image_code_from_redis:
# 没有读取到redis中的图形验证码 —— 可能过期了
return JsonResponse({
'code': 400,
'errmsg': '图形验证码过期!'
}, status=403)
# 读取到了redis的验证码是字符串的字节形式,需要转化成字符串
image_code_from_redis = image_code_from_redis.decode()
# 2.4.2、和用户手写的比对
# 'ABCE' != 'ABCD'
if image_code.lower() != image_code_from_redis.lower(): # 全部转为小写比较,目的是忽略大小写
return JsonResponse({
'code': 400,
'errmsg': '验证码输入有误'
}, status=400)
# 3、数据处理 —— 发送手机短信
# 3.0、判断redis的短信标志存不存在 —— 存在说明60秒之内用户发送过短信
send_flag = conn.get('send_flag_%s' % mobile)
if send_flag:
return JsonResponse({'code': 400, 'errmsg': '请勿重复发送'}, status=403)
# 3.1、生成6位短信验证码
sms_code = "%06d" % random.randint(0, 999999)
print("短信验证码: ", sms_code)
# 3.2、短信验证码存入redis缓存
# 3.2.1、通过redis链接对象获取一个管道
pl = conn.pipeline()
# 短信验证码存入redis中,便于用户注册的时候读取比对
# 以手机号码,作为存入短信验证码的redis中key
# 通过pl管道对象,调用的函数(执行指令),此处并没有真正的执行,而是暂存
pl.setex(
'sms_%s' % mobile,
300,
sms_code
)
# conn.setex(
# 'sms_%s' % mobile,
# 300,
# sms_code
# )
# 3.3、存入一个标志 —— 表示用户在60秒内发送了短信
pl.setex(
'send_flag_%s' % mobile,
60,
'1'
)
# conn.setex(
# 'send_flag_%s' % mobile,
# 60,
# '1'
# )
# 批量执行管道中暂存的指令
pl.execute()
# 3.4、调用容联云接口发送短信
# 发送短信验证码
CCP().send_template_sms(
mobile,
[sms_code, 5],
1
)
# 4、构建响应
return JsonResponse({
'code': 0,
'errmsg': 'ok'
})
3:路由映射:
path('sms_codes/<mobile:mobile>/', views.SMSCodeView.as_view())
三:出现的问题:
1:删除图形验证码:
问什么要删除?图形验证码写错了,请求了,这个验证码就不能再用了。如果不设置只能用一次那么,爬虫就会一直尝试。不安全。
怎么做?读一次删一次。 conn.delete(‘img_%s’%uuid)
2:注册接口补充:

# 验证码业务流程:
# 连接数据库,在数据库中查询出验证码,如果没有查到,说明验证码过期了。
# 如果验证码和用户输入不一致则验证码输入错误。
conn = get_redis_connection("verify_code")
sms_code_from_redis = conn.get("sms_%s" % mobile)
if not sms_code_from_redis:
return JsonResponse({
"code":400,
"errmsg": "验证码过期",
}, status=403)
if sms_code_from_redis != sms_code:
return JsonResponse({
"code": 400,
"errmsg": "验证码错误",
}, status=400)
3:图形验证码忽略大小写:
if image_code.lower() != image_code_from_redis.lower(): # 全部转为小写比较,目的是忽略大小写
return JsonResponse({
'code': 400,
'errmsg': '验证码输入有误'
}, status=400)
4:避免频繁发送验证码:



浙公网安备 33010602011771号