选项 | 方案 |
---|---|
请求方法 | GET |
请求地址 | image_codes/(?P[\w-]+)/ |
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
uuid | string | 是 | 唯一编号 |
生成图形验证码接口只提供GET即可
通用调用captcha.generate_captcha()即可生成图形验证码
将验证码文件部分保存到redis中,以使后面校验用
# ./lgshop/dev.py
"verify_code": {
# 验证码
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/2",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
# ./verifications/views.py
from django.shortcuts import render
from django.views import View
from .libs.captcha.captcha import captcha
from django_redis import get_redis_connection
from django import http
class ImageCodeView(View):
"""图形验证码"""
def get(self,request,uuid):
'''
:param request:
:param uuid: 通用唯一识别符,用于标识唯一图片验证码属于哪个用户的
:return: image/jpg
'''
# 生成图片验证码
text, image = captcha.generate_captcha()
# print(text, image)
# 保存图像验证码,保存到redis
redis_conn = get_redis_connection('verify_code')
# name time value
redis_conn.setex('img_%s' % uuid, 300, text)
# 响应图形验证码
return http.HttpResponse(image, content_type='image/png')
# ./verifications/urls.py
from django.urls import path, re_path
from . import views
urlpatterns = [
# 图形验证码 \w [A-Za-z0-9_]- uuid 78b4d5b7-5157-4b2a-bf48-ba616e169d66
re_path(r'^image_codes/(?P[\w-]+)/$' , views.ImageCodeView.as_view())
]
# ./static/js/register.js
data: {
// 数据对象
// ... ...
image_code_url: '',
uuid: '',
// 页面加载完成之后会被调用的方法
mounted(){
// 生成图形验证码
this.generate_image_code()
},
methods: {
// 生成图片验证码
generate_image_code(){
// uuid 发生变化
this.uuid = generateUUID();
this.image_code_url = '/image_codes/'+ this.uuid +'/'
},
from ronglian_sms_sdk import SmsSDK
accId = '容联云通讯分配的主账号ID'
accToken = '容联云通讯分配的主账号TOKEN'
appId = '容联云通讯分配的应用ID'
def send_message():
sdk = SmsSDK(accId, accToken, appId)
tid = '1' # 应用是系统提供的开发测试模板及编号
mobile = '手机号1,手机号2'
datas = ('变量1', '变量2')
resp = sdk.sendMessage(tid, mobile, datas)
result=json.load(resp)
if result["statusCode"]=="000000":
return 0
else:
return -1
if __name__=="__main__":
send_message()
class CCP(object):
"""发送短信的单例类"""
def __new__(cls,*args,**kwargs):
if not hasattr(cls,"_instance"):
cls._instance=super().__new__(cls,*args,**kwargs)
cls._instance.sdk=SmsSDK(accId, accToken, appId)
return cls._instance
from ronglian_sms_sdk import SmsSDK
import json
accId = '容联云通讯分配的主账号ID'
accToken = '容联云通讯分配的主账号TOKEN'
appId = '容联云通讯分配的应用ID'
class CCP(object):
"""发送短信的单例类"""
def __new__(cls, *args, **kwargs):
# 如果是第一次实例化,应该返回实例化后的对象,如果是第二次实例化,应该返回上一次实例化后的对象
# 判断是否存在类属性 _instance
if not hasattr(cls, "_instance"):
cls._instance = super().__new__(cls, *args, **kwargs)
cls._instance.sdk = SmsSDK(accId, accToken, appId)
return cls._instance
def send_message(self, tid, mobile, datas):
sdk = self._instance.sdk
# tid = '容联云通讯创建的模板ID'
# mobile = '手机号1,手机号2'
# datas = ('变量1', '变量2')
# tid = '1'
# mobile = '18908656327'
# datas = ('2345', '5')
resp = sdk.sendMessage(tid, mobile, datas)
result = json.loads(resp)
if result["statusCode"] == "000000":
return 0
else:
return -1
if __name__ == "__main__":
c = CCP()
c.send_message("1", "18908656327", ("1234", "5")) # 测试1号模板,手机号,(短信验证码,有效时间)
|选项|方案|
|请求方法|GET|
|请求地址|/sms_codes/(?P1[3-9]\d{9})/|
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
mobile | string | 是 | 手机号 |
image_code | string | 是 | 图形验证码 |
uuid | string | 是 | 唯一编号 |
字段 | 说明 |
---|---|
code | 状态码 |
errmsg | 错误信息 |
class SMSCodeView(View):
'''短信验证码发送'''
def get(self,request,mobile):
'''
:param request:
:param mobile:
:return:
'''
# http://127.0.0.1:8000/sms_codes/手机号/?uuid=cea94f82-4329-41e4-80df-cca815875a43&image_code=XQDI
# 接收参数,校验参数
# print(mobile)
uuid = request.GET.get('uuid') # uuid
image_code_client = request.GET.get('image_code') # 图形验证码,查看前端JS中传递参数名称(不是表单提交)
if not all([uuid, image_code_client]):
return http.HttpResponseForbidden('缺少必传参数') # HttpResponseForbidden:返回403 status code.
# 提取图形验证码
redis_conn = get_redis_connection('verify_code')
# 判断用户是否频繁发生短信验证码
send_flag = redis_conn.get('send_flag_%s' % mobile)
if send_flag:
return http.JsonResponse({
'code': RETCODE.THROTTLINGERR, 'errmsg': '发送短信过于频繁'})
image_code_server = redis_conn.get('img_%s' % uuid)
# 提取图形验证码失效了
if image_code_server is None:
return http.JsonResponse({
'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码已失效'})
# 删除图形验证码
redis_conn.delete('img_%s' % uuid)
# 对比图形验证码
# print(image_code_client) # kl5X
# print(image_code_server)
image_code_server = image_code_server.decode()
if image_code_client.lower() != image_code_server.lower():
return http.JsonResponse({
'code': RETCODE.IMAGECODEERR, 'errmsg': '输入图形验证码有误'})
# 生成短信验证码
# 生成6位的随机数 %6d
sms_code = "%06d" % random.randint(0, 999999)
# 保存短信验证码
redis_conn.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
# 保存发送短信验证码的标记
redis_conn.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_TIMES, 1)
# 发送短信 send_message(self, mobile, datas, tid): 300/60 浮点数
CCP().send_message( constants.SEND_SMS_TEMPLATE_ID, mobile, (sms_code, constants.SMS_CODE_REDIS_EXPIRES//60))
# 响应结果
return http.JsonResponse({
'code': RETCODE.OK, 'errmsg': '发送短信验证码成功'})
re_path(r'^sms_codes/(?P1[3-9]\d{9})/$' , views.ImageCodeView.as_view()),
# ./templates/register.html
<li>
<label>短信验证码:</label>
<input type="text" v-model="sms_code" @blur="check_sms_code" name="sms_code" id="msg_code" class="msg_input">
<a @click="send_sms_code" class="get_msg_code">[[ sms_code_tip ]]</a>
<span class="error_tip" v-show="error_sms_code">[[ error_sms_code_message ]]</span>
</li>
axios.get(url,{
responseType: 'json'})
// 发送短信验证码 ajax
send_sms_code(){
//校验手机号和图形验证码
this.check_mobile();
this.check_image_code();
// alert(this.error_mobile);
// alert(this.error_image_code);
if (this.error_mobile ==true || this.error_image_code==true){
// 如果有误,不发送短信验证码申请
return;
}
let url = '/sms_codes/'+ this.mobile +'/?uuid='+ this.uuid +'&image_code=' + this.image_code;
alert(url)
axios.get(url,{
responseType: 'json'
})
.then(response => {
//请求正常
if (response.data.code == '0'){
//返回成功
// 展示倒计时60秒
let num = 60;
// setInterval('回调函数', '时间间隔(毫秒)')
let t = setInterval(()=>{
if (num == 1){
// 停止回调函数
clearInterval(t);
this.sms_code_tip = '获取短信验证码';
// 重新生成图形验证码
this.generate_image_code();
this.send_flag = false;
}else{
num -= 1;
this.sms_code_tip = num + '秒';
}
}, 1000)
}else{
if(response.data.code == '4001'){
// 图形验证码错误
this.error_sms_code_message = response.data.errmsg;
this.error_sms_code = true;
}else {
// 短信证码错误
this.error_sms_code_message = response.data.errmsg;
this.error_sms_code = true;
}
this.send_flag = false;
}
})
.catch(error => {
//请求异常
console.log(error.response);
this.send_flag = false;
})
},
# 短信验证码
sms_code_client = register_form.cleaned_data.get('sms_code')
# 判断短信验证码输入是否正确
redis_conn = get_redis_connection('verify_code')
sms_code_server = redis_conn.get('sms_%s' % mobile)
if sms_code_server.decode() is None:
return render(request, 'register.html', {
'sms_code_errmsg': '短信验证码已失效'})
# print(sms_code_server.decode())
# print(sms_code_client)
if sms_code_server.decode() != sms_code_client:
return render(request, 'register.html', {
'sms_code_errmsg': '输入短信验证码有误'})
{
% if sms_code_errmsg %}
<span class="error_tip">
{
{
sms_code_errmsg }}
</span>
{
% endif %}
# 创建管道
pl = redis_conn.pipeline()
# 将命令添加到队列
# 保存短信验证码
pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
# 保存发送短信验证码的标记
pl.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_TIMES, 1)
# 执行
pl.execute()