功能简介:
前端jq生成唯一UUID传递给后台,后台获取到UUID后生成图片验证码,并将UUID和验证码绑定保存到redis缓存数据库,设置过期时间为1分钟。
将图片验证码返回给前端,前端提交验证码,后台进行验证,验证通过则返回一个短信验证码给前端,并保存到redis,设置计时器,否则抛出异常。
前端获取到短信验证码后提交给后台,经过验证后返回相应数据。
1、前端jQuery验证表单
function req_msg() {
// alert(current_id)
// 1、拼接请求路径路径 GET /msg_code/?image_id=uuid&image_text=mytext&phone=12345678
var image_id = current_id;
var username = $('#username').val();
var password = $('#password').val();
var cpassword = $('#cpassword').val();
var image_text = $('#checkcode').val();
var phone = $('#phone').val();
var msgurl = 'http://127.0.0.1:8000/image/msg_code/?image_id='+image_id+'&image_text='+image_text+'&phone='+phone;
// alert(msgurl)
console.log(msgurl);
var reg_uuid = /^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$/;
var reg_text = /^[\w]{4}$/;
var reg_phone = /^1[3458][0-9]\d{4,8}$/;
if(!username){
alert('用户名为空');
return
}
if(password !== cpassword){
alert('两次密码不一致');
return
}
if (!reg_uuid.test(image_id)){
console.log("UUID错误");
return
}
if (!reg_text.test(image_text)){
console.log("验证码错误");
return
}
if (!reg_phone.test(phone)){
console.log("手机号码错误");
return
}
// 2、通过ajax发送请求
$.ajax({
url:msgurl,
method:'GET',
contentType:'application/json',
success:function () {
alert('请求成功')
},
error:function (data) {
console.log(data)
}
})
}
2、后台生成验证码
class ImageView(APIView):
def get(self, request, image_id):
# image_id为前端传递过来的图形验证码对应的唯一ID
# 使用captcha生成图片验证码,text为图片上的验证码,image为验证码图片
text, image = captcha.generate_captcha()
# 连接之前设置的redis数据库
conn_obj = get_redis_connection('valid')
# 将验证码写入缓存数据库
conn_obj.setex(image_id, constants.IMAGE_UUID_REDIS_EXPIRE, text)
# 返回验证码图片到前端
HttpResponse(image, content_type='image/jpg')
3、后台验证图片验证码和短信验证码
class ImageTextSer(serializers.Serializer):
image_id = serializers.UUIDField()
image_text = serializers.CharField(max_length=4, min_length=4)
phone = serializers.CharField(max_length=11, min_length=11)
def validate(self, attrs):
image_uuid = attrs['image_id']
image_input_code = attrs['image_text']
phone = attrs['phone']
# 验证,与redis数据库里的对比
redis_con_obj = get_redis_connection('valid')
# 从redis取出的是bytes类型
uuid_redis = redis_con_obj.get('%s' % image_uuid)
image_redis_code = uuid_redis.decode()
print(image_redis_code)
print(image_input_code)
if image_redis_code.upper() != image_input_code.upper():
# print("ASDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD")
# print("验证码错误")
raise serializers.ValidationError('验证码错误')
# 取出手机号码对应的发送标志,如果能取到,说明已经在1分钟内发送过验证码
flag = redis_con_obj.get('%s_flag' % phone)
if flag:
raise serializers.ValidationError('请不要再1分钟内重复请求验证码')
return attrs
class MsgCode(GenericAPIView):
serializer_class = serializers.ImageTextSer
def get(self, request):
"""
1、校验图片验证码
2、5分钟内不能重复发送验证码:利用redis有过期时间的特点,在redis中设置5分钟发送短信的标志flag
3、生成6位短信验证码
4、保存短信验证码
5、发送短信
6、返回响应数据
:param request:
:return:
"""
# 1、验证图片
query_dict = request.query_params
# query_dict = request.data
print("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
print(query_dict)
# 获取序列化器并实例化
serial = self.get_serializer(data=query_dict)
# 验证
serial.is_valid(raise_exception=True)
# 图片验证码验证通过后才能进行短信验证码生成返回及验证
# 生成短信验证码
msg_phone = '%04d' % random.randint(0, 9999)
print('手机验证码', msg_phone)
# 保存到redis
phone = query_dict['phone']
con_obj = get_redis_connection('valid')
con_obj.setex('%s_msg' % phone, constants.PHONE_MSG_CODE_EXPIRE, msg_phone)
con_obj.setex('%s_flag' % phone, constants.PHONE_MSG_CODE_EXPIRE, msg_phone)
return Response(msg_phone)