之前我做了图片验证码的逻辑,然后为了完成注册,我需要再让用户验证一次手机号码。
为了验证手机号码,我必须获取用户的手机,还需要先验证图片验证码。所以在发送手机验证码之前,我需要先验证用户的手机号码和图片验证码
因为需要验证数据,就可以使用一下serializer了
先简单的搭一个view和serializer。由于这里get方法并没有保存任何值,并且需要指定序列化器,我使用GenericView来写view类
现在给这个视图写一个serializer,这个serializer没有和任何的mysql模型类产生关系,所以直接用最基础的serializer就可以了,然后我们可以先给serializer添加我们需要的字段,首先手机号码和用户第一次输入的验证码部分是肯定要的,还有就是图片验证码的ID
我先在serializer中补全我的验证逻辑即复写validata方法,并传入需要验证的三个字段
def validate(self, attrs):
print(attrs)
image_id_uuid=attrs['image_id']
image_input_text=attrs['image_text']
phone=attrs['phone']
然后获得了从前端传入的数据后,我们需要和之前存在redis数据库中的数据进行对比验证。这时候我们通过UUID去取存在数据库中的数据,注意我们的redis数据库中的验证图片是有过期时间的,所以过期了需要重新获取一遍。
from django_redis import get_redis_connection
class Img_CodeSerializer(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_id_uuid=attrs['image_id']
image_input_text=attrs['image_text']
phone=attrs['phone']
redis_con_obj = get_redis_connection('valid')
correct_image_text = redis_con_obj.get('%s' % image_id_uuid)
correct_image_text=correct_image_text.decode()
if (correct_image_text.lower() != image_input_text.lower()):
raise serializers.ValidationError('captcha is not valiable')
return attr
‘%s’%是一个将后面的内容转化为字符串的占位符,这里我们获得到了我们的图片文字数据text,因为之前保存setx方法中指定了image_id_uuid是键名,text为值,所以取出来的就是文字数据text了,但是这个数据是一个二进制数据,所以要给他decode()一下获得字符串数据。最后把输入的验证码和redis存储的验证码比对就可以验证了。到这里我们的serializer就写好了。
这里我们需要用视图来获取用户传给后端的数据来使用serializer进行验证。但目的是为了让后端发送一个手机验证码给用户,所以这里是一个get请求而不是post。
所以暂时代码逻辑应该如下所示
from . import serializers
class Msg_code(GenericAPIView):
serializer_class = serializers.Img_CodeSerializer
def get(self,request):
query_dict=request.query_params
serializer=self.get_serializer(data=query_dict)
serializer.is_valid(raise_exception=True)
为了实现短信验证码,我们需要用户的手机号码,之前我们已经获取过了,然后还有一个手机验证码的过期时间和一个是否过期的验证,还需要一个发送手机验证码的办法。
由于这个操作是一个耗时操作,所以之后我会把发送操作放入celery中进行,但现在我仍然是在view中实现的。
import random
msg='%04d'%random.randint(0,9999)
#生成一个4位的验证码 '%04d'为这个4位数字补0
print('msg_captcha',msg)
redis_con_obj=get_redis_connection('valid')
phone=query_dict['phone']
redis_con_obj.setex('%s_msg'%phone,constants.PHONE_MSG_CODE_EXPIRES,msg)
#将验证码存入redis数据库,设置过期时间,过期时间来源于constants.py中的常量,别忘记设置
redis_con_obj.setex('%s_flag'%phone,constants.PHONE_FLAG_CODE_EXPIRES,1)
#再给手机号码验证码设置一个验证过期时间的flag,过期时间来源于constants.py中的常量,别忘记设置
这里我们就生成了手机验证码和校验验证码过期的两个东西,然后在serializer中添加一下检验字段
flag = redis_con_obj.get('%s_flag' % phone)
if flag:
raise serializers.ValidationError('do not send code until 1 minutes later')
这个字段在每次发送验证码的时候都会经过一次is_valid()的验证所以不需要再往view视图里面添加字段。
直接搜索容联云就可以找到容联云了,这是一个发送手机验证码等服务的通信平台,至于注册什么的,我就不详细写了
将该第三方包放入python方法
这里我是直接百度找到的第三方包,经过大腿修改的,直接在sms.py中修改配置就可以了,由于隐私问题就不把配置文件放出来了
在view视图中添加
from webbacksoftware.libs.yuntongxun.sms import CCP
ccp=CCP()
ret_data=ccp.send_template_sms(phone,[msg,'1'],1)
print(ret_data)
return HttpResponse('okay')
这里就完成后端发送验证码的逻辑了
url(r'^users/msg_code/$',views.Msg_code.as_view()),
在urlpattern中添加以下字段注册视图
首先仍然需要先验证一下前端中的一些数据
需要在入口函数中添加一下字段验证数据
$('#code-btn').click(function () {
image_id = current_id
image_text = $('#checkcode').val()
phone = $('#phone').val()
// 2) 将获取到的数据进行正则的校验
var reg_uuid = /^[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}$/
var reg_text = /^[\w]{4}$/
var reg_phone = /^1[3456789]\d{9}$/
console.log(reg_uuid.exec(image_id))
console.log(reg_uuid.test(image_id))
// 3) 利用正则进行校验,如果校验不通过,则返回弹窗
if(!reg_uuid.test(image_id)){
alert('图片校验未通过')
}
if(!reg_text.test(image_text)){
alert('验证码校验未通过')
}
if(!reg_phone.test(phone)){
alert('手机号校验未通过')
}
})
})
在点击发送验证码时进行一系列的验证
msg_url = 'http://127.0.0.1:8000/users/msg_code/?image_id='+image_id+'&image_text='+image_text+'&phone='+phone
这段请求带了验证码图片ID 用户输入验证码 用户手机号3个字段的内容传给后端
我们只要把这三个字段用ajax传回就好了
$.ajax({
url:msg_url,
method:'GET',
contentType:'application/json',
success:function (data) {
console.log(data)
},
error:function (data) {
console.log(data)
}
})