首页 > 技术文章 > 13Django-在用户注册代码中完成手机验证码的比对

tyjs09 2021-12-14 13:00 原文

验证码功能流程:

1前端页面点击《免费获取验证码》按钮,发送Ajax请求到后端

2后端接到请求后:

1)生成随机验证码

2)存储验证码

3)发送验证码

3前端注册时提交验证码,后端在注册逻辑中对比验证码是否正确

前端:

1编写ajax发送请求,给发送按钮绑定事件

function regist() {
        <!--使用jquery拿数据-->
        var username = $('.username').val();
        var email = $('.email').val();
        var password1 = $('.password_1').val();
        var password2 = $('.password_2').val();
        var phone = $('.phone').val();
        var sms_num = $('.sms_num').val();
        <!--组织json对象-->
        var post_data = {"username":username, "email":email, "password1":password1, "password2":password2, "phone":phone,"sms_num":sms_num}
        <!--提交数据-->
        $.ajax({
            type:"post",
            contentType:"application/json",
            dataType:"json",
            <!--把json对象转化成json字符串-->
            data:JSON.stringify(post_data),
            url:"http://127.0.0.1:8000/v1/users",
            success:function (result) {
                if (result.code == 200){
                    alert('注册成功')
                }else{
                    alert('注册失败')
                }

            }
        })
    }

    function sendSMS() {
        var phone = $('.phone').val();
        var post_data = {"phone":phone};
        $.ajax({
            type:"post",
            contentType: "application/json",
            dataType: "json",
            url:"http://127.0.0.1:8000/v1/users/sms/duanxin",
            data:JSON.stringify(post_data),
            success:function (result) {
                if (result.code == 200){
                    alert("短信发送成功")
                }else{
                    alert(result.error)
                }
            }

        })
    }
    </script>

后端:

一redis软件准备

1在windows里安装redis并配置环境变量:

链接:https://pan.baidu.com/s/1DlgCMEfv97U9v8EV3KMZZA 提取码:abcd

2配置环境变量:

把安装目录D:\Program Files\Redis配置到windows环境变量里

3打开cmd窗口执行命令redis-cli进行测试

二在django的setting里配置redis缓存

1)安装django-redis库

pip install django-redis

2)在setting.py里配置缓存:

#django-redis配置(将django与redis融合)
CACHES = {
    "default":{
        "BACKEND": "django_redis.cache.RedisCache",
        #指定1库
        "LOCATION": "redis:127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            #"PASSWORD":"123456"
        }
    }
}

3在Djangoshell里进行测试方法1:

D:\PycharmProjects\linuxTangblog>python manage.py shell
>>> from django.core.cache import cache
>>> d = ['a','b','c']
>>> cache.set('testk',d,900) #把d存入缓存,失效时间900秒
True
>>> cache.get('testk')
['a', 'b', 'c']
>>>

4在Djangoshell里进行测试方法2:

>>> from django_redis import get_redis_connection
>>> r = get_redis_connection()
>>> r
Redis<ConnectionPool<Connection<host=None,port=6379,db=0>>>
>>> r.set('k1','v1')
True
>>> r.get('k1')
b'v1'
>>>

5在cmd里测试:

D:\PycharmProjects\linuxTangblog>redis-cli
127.0.0.1:6379> keys * #查看所有的key
1) ":1:testk"
127.0.0.1:6379> ttl ":1:testk" #查看还有多久过期
(integer) 321
127.0.0.1:6379>

6在注册视图里引入发送短信的类,然后编写发送短信方法:

from django.core.cache import cache
from tools.sms import Yuntongxin
from django.conf import settings
#短信
def sms_view(request):
    if request.method != 'POST':
        result = {'code':201,'error':'请求方式并非post'}
        return JsonResponse(result)
    #获取请求体
    json_str = request.body
    #转换成字典
    json_obj = json.loads(json_str)
    #获取手机号
    phone = json_obj.get('phone')
    print(phone)
    #生成随机码
    code = random.randint(1000,9999)
    print('phone',phone,'code',code)
    #存储随机码900秒过期(库django-redis)pip install django-redis
    cache_key = 'sms_%s'%(phone)
    cache.set(cache_key,code,900)
    #发送随机码
    send_sms(phone,code)
    return JsonResponse({'code':200})

#发短信
def send_sms(phone,code):
    config = {
        "accountSid": settings.SMS_ACCOUNT_SID,
        "accountToken": settings.SMS_ACCOUNT_TOKEN,
        "appId": settings.SMS_APPID,
        "templateId": settings.SMS_TEMPLATEID,
    }
    yun = Yuntongxin(**config)
    res = yun.run(phone, code)
    return res

7完善注册视图逻辑添加演技验证码比对逻辑::

 def post(self,request):
        sms_num = json_obj.get('sms_num')
        #从库里查注册时填写的code
        old_code = cache.get('sms_%s'%(phone))
        if not old_code:
            result = {'code':'405','error':'验证码已过期'}
            return JsonResponse(result)
        #客户提交的code可库里的code进行比对
        if int(sms_num) != old_code:
            result = {'code': '405', 'error': '验证码不匹配'}
            return JsonResponse(result)

8完整的用户注册视图代码如下:

import json,random,hashlib
from django.core.cache import cache
from django.http import JsonResponse
from django.shortcuts import render
from django.utils.decorators import method_decorator
from django.views import View
from .models import UserProfile
from tools.logging_dec import logging_check
from tools.sms import Yuntongxin
from django.conf import settings
# Create your views here.
class UserViews(View):
    #获取个人信息
    def get(self,request,username=None):
        if username:
            #/v1/users/zhangsan
            try:
                user = UserProfile.objects.get(username=username)
            except Exception as e:
                result = {'code':208, 'error':'用户名不存在'}
                return JsonResponse(result)
            result = {'code':200,'username':username, 'data':{'info':user.info,'sign':user.sign,'nickname':user.nickname,'avatar':str(user.avatar)}}
            return JsonResponse(result)
    #用户注册
    def post(self,request):
        json_str = request.body #获取前端的json提交
        json_obj = json.loads(json_str) #把json串转换成python的对象
        username = json_obj.get('username')
        email = json_obj.get('email')
        password1 = json_obj.get('password1')
        password2 = json_obj.get('password2')
        phone = json_obj.get('phone')
        sms_num = json_obj.get('sms_num')
        #参数的基本检查
        if password1 != password2:
            result = {'code':206,'error':'两次提交密码不一致'}
            #把json对象转换成json串返给浏览器
            return JsonResponse(result)
        #1检查用户名是否可用
        queryset_users = UserProfile.objects.filter(username=username)
        if queryset_users:
            result = {'code':207,'error':'用户名已存在'}
            return JsonResponse(result)
        #手机号不能重复
        queryset_phone = UserProfile.objects.filter(phone=phone)
        if queryset_phone:
            result = {'code':210,'error':'手机号已存在'}
            return JsonResponse(result)
        #比对手机验证码
        old_code = cache.get('sms_%s'%(phone))
        print(old_code)
        if not old_code:
            result = {'code':'405','error':'验证码已过期'}
            return JsonResponse(result)
        print(sms_num)
        if int(sms_num) != old_code:
            result = {'code': '405', 'error': '验证码不匹配'}
            return JsonResponse(result)


        #给明文密码加密
        hash_object = hashlib.md5()
        hash_object.update(password1.encode()) #md5要求字节串而password1是字符串,必须转换
        pwd = hash_object.hexdigest()
        #已经设置默认值的字段,在创建订单时可以不写
        UserProfile.objects.create(username=username,nickname=username,password=pwd,email=email,phone=phone)
        result = {'code':200,'username':username,'data':{}}
        return JsonResponse(result)
    #更新用户信息[昵称,签名,个人描述]
    @method_decorator(logging_check)
    def put(self,request,username=None):
        #获取所有数据
        json_str = request.body
        #把json串转换成字典
        json_obj = json.loads(json_str)
        # #取用户(一查)
        # try:
        #     user = UserProfile.objects.get(username=username)
        # except Exception as e:
        #     result = {'code':208,'error':'用户名不存在'}
        #     return JsonResponse(result)
        user = request.myuser
        #修改数据(二改)
        user.sign = json_obj['sign']
        user.info = json_obj['info']
        user.nickname = json_obj['nickname']
        #保存数据(三更新)
        user.save()
        return JsonResponse({'code':200})



#修改头像
@logging_check
def users_views(request,username):
    if request.method != 'POST':
        result = {'code':201,'error':'请求方式并非post'}
        return JsonResponse(result)
    # try:
    #     user = UserProfile.objects.get(username=username)
    # except Exception as e:
    #     result = {'code':208, 'error':'用户名不存在'}
    #     return JsonResponse(result)
    user = request.myuser
    avatar = request.FILES['avatar']
    user.avatar = avatar
    user.save()
    return JsonResponse({'code':200})

#短信
def sms_view(request):
    if request.method != 'POST':
        result = {'code':201,'error':'请求方式并非post'}
        return JsonResponse(result)
    #获取请求体
    json_str = request.body
    #转换成字典
    json_obj = json.loads(json_str)
    #获取手机号
    phone = json_obj.get('phone')
    print(phone)
    #生成随机码
    code = random.randint(1000,9999)
    print('phone',phone,'code',code)

    #检查是否有发过并且未过期的验证码(安全防范)
    cache_key = 'sms_%s' % (phone)
    old_code = cache.get(cache_key)
    if old_code:
        return JsonResponse({'code':406,'error':'900秒内已经发送过验证码'})
    # 存储随机码900秒过期(库django-redis)pip install django-redis
    cache.set(cache_key,code,900)
    #发送随机码
    send_sms(phone,code)
    return JsonResponse({'code':200})

#发短信
def send_sms(phone,code):
    config = {
        "accountSid": settings.SMS_ACCOUNT_SID,
        "accountToken": settings.SMS_ACCOUNT_TOKEN,
        "appId": settings.SMS_APPID,
        "templateId": settings.SMS_TEMPLATEID,
    }
    yun = Yuntongxin(**config)
    res = yun.run(phone, code)
    return res

 

推荐阅读