django-实现登录短信验证

该博客详细介绍了如何在Django项目中实现登录时的短信验证功能,包括前端Ajax调用、后端核心逻辑如发送验证码、验证码检查、集成Redis作为缓存以及统一接口返回结果的方法。通过Django集成Redis模块,存储短信验证码并控制其生命周期,确保数据的安全性和高效性。此外,还涉及到了短信下发的流程和验证码的校验机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

功能演示

在这里插入图片描述

核心任务

前端功能:

  1. 点击按钮Ajax调用发送验证码功能
  2. 输完验证码后Ajax调用验证功能

后端功能:

功能1:发送验证码功能
功能2:验证码检查

后台核心逻辑(不需要手写)

功能3:发短信
功能4:生成短信验证码(随机生成6位数字)

集成Redis

使用Redis代替session缓存, 存储数据!
Redis集成到Django中!

扩展功能:

统一接口返回结果的规范方法!

功能1:Django集成Redis

因为我们短信验证码生命周期控制的非常严格!而且数据用完后不需要存储. 所以建议直接把数据存储在缓存/内存中!

方案1: 使用session或cookie存储! session在当前浏览器有效! cookie存储在用户本地不安全!session和cookie操作复杂,时间控制不精准!,存储的数据量非常有限!
方案2: 使用Redis/Mongdb等key:value数据库!读写非常快, 存储数据量非常庞大, 有效期控制非常精准!

第一步: 下载django-redis模块

pip install django-redis

第二步: 配置setting.py中写配置

配置Redis为Django的缓存,替换原来的session

1. #配置Redis为Django缓存
2. CACHES = {
3. "default": {
4. "BACKEND": "django_redis.cache.RedisCache",
5. "LOCATION": "redis://127.0.0.1:6379/0", #地址
6. "OPTIONS": {
7. "CLIENT_CLASS": "django_redis.client.DefaultClient",
8.  }
9.  }
10. }
11. # 将session缓存在Redis中
12. SESSION_ENGINE = "django.contrib.sessions.backends.cache"
13. SESSION_CACHE_ALIAS = "default"
14. # session 设置(可以不写)
15. SESSION_COOKIE_AGE = 60 * 60 * 12 # 12小时
16. SESSION_SAVE_EVERY_REQUEST = True
17. SESSION_EXPIRE_AT_BROWSER_CLOSE = True # 关闭浏览器,则COOKIE失效

第三步: views导入缓存cache模块

from django.core.cache import cache

第四步: 使用

1. def test_redis(request):
2.  # 存储数据
3.  chache.set("name", "tom", 20) # 该值的有效期为20s
4.   # 判断Redis中是否存在
5.  print(cache.has_kay("name"))  # 包含: true
6.   # 获取
7.    print(cache.get("name"))  # 返回: tom  无返回null
8.  return HttpResponse("测试Redis")

功能2: 短信下发
第一步: 申请短信服务
第二步: 独立发送短信和生成验证码的模块

#!/usr/bin/env python
#coding=utf-8
import random
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest
from utils import restful
def send_sms(phone,code):
    client = AcsClient('mxTYXZ4QDQecJQDN', 'znxNezmm4zfA9k
    Pyqx1WrpznjCaJFT', 'cnhangzhou')
    #phone = '17600950805'
    #aa= '222222'
    code = "{'code':%s}"%(code)
    request = CommonRequest()
    request.set_accept_format('json')
    request.set_domain('dysmsapi.aliyuncs.com')
    request.set_method('POST')
    request.set_protocol_type('https') # https | http
    request.set_version('2017-05-25')
    request.set_action_name('SendSms')
    request.add_query_param('RegionId', 'cn-hangzhou')
    request.add_query_param('PhoneNumbers', phone)
    request.add_query_param('SignName', '北网')
    request.add_query_param('TemplateCode',             'SMS_162738723')
    request.add_query_param('TemplateParam',code )
    response = client.do_action(request)
    # python2: print(response)
    print(str(response, encoding = 'utf-8'))
    return str(response, encoding = 'utf-8')
#数字表示生成几位, True表示生成带有字母的 False不带字母的
def get_code(n=6,alpha=True):
    s = '' # 创建字符串变量,存储生成的验证码
    for i in range(n): # 通过for循环控制验证码位数
            num = random.randint(0,9) # 生成随机数字0-9
            if alpha: # 需要字母验证码,不用传参,如果不需要字母的,
            关键字alpha=False
                upper_alpha = chr(random.randint(65,90))
                lower_alpha = chr(random.randint(97,122))
                num = random.choice([num,upper_alpha,lower_alpha])
            s = s + str(num)
    return s
if __name__ == '__main__':
    send_sms('18434288349', get_code(6,False))
    print(get_code(6,False)) # 打印6位数字验证码
    print(get_code(6,True)) # 打印6位数字字母混合验证码
    print(get_code(4,False)) # 打印4位数字验证码
    print(get_code(4,True)) # 打印4位数字字母混合验证码

功能3: 后台功能: 发送短信接口
流程:
获取手机号---->生成6位验证码–>缓存验证码到Redis—>发短信–>返回状态

# 发短信接口
def sms_send(request):
    # http://localhost:8000/duanxin/duanxin/sms_send/?phone=18434288349
    # 1 获取手机号
    phone = request.GET.get('phone')
    # 2 生成6位验证码
    code = aliyunsms.get_code(6, False)
    # 3 缓存到Redis
    cache.set(phone,code,60) #60s有效期
    print('判断缓存中是否有:',cache.has_key(phone))
    print('获取Redis验证码:',cache.get(phone))
    # 4 发短信
    result = aliyunsms.send_sms(phone, code)
    return HttpResponse(result)

功能4: 短信验证码校验
流程:
获取前台电话和验证码----> 获取Redis中存的验证码—>对比是否相等–>返回结果

# 短信验证码校验
def sms_check(request):
    # /duanxin/sms_check/?phone=xxx&code=xxx
    # 1. 电话和手动输入的验证码
    phone = request.GET.get('phone')
    code = request.GET.get('code')
    # 2. 获取redis中保存的code
    print('缓存中是否包含:',cache.has_key(phone))
    print('取值:',cache.get(phone))
    cache_code = cache.get(phone)
    # 3. 判断
    if code == cache_code:
        return HttpResponse(json.dumps({'result':'OK'}))
    else:
        return HttpResponse(json.dumps({'result':'False'}))

手动在浏览器上给假设的参数进行测试:

http://localhost:8000/duanxin/sms_send/?phone=手机号
http://localhost:8000/duanxin/sms_check/?phone=手机号&code=验证码

功能5: 统一接口的数据格式:

参考:

https://blog.youkuaiyun.com/xyy1028/article/details/84981627
https://www.runoob.com/w3cnote/restful-architecture.html

统一的接口模块restful.py

#encoding: utf-8
from django.http import JsonResponse
class HttpCode(object):
    ok = 200
    pageerror = 404
    methoderror = 405
    servererror = 500
# {"code":400,"message":"","data":{}}
def result(code=HttpCode.ok,message="",data=None,kwargs=None):
    json_dict = {"code":code,"message":message,"result":data}
    if kwargs and isinstance(kwargs,dict) and kwargs.keys():
        json_dict.update(kwargs)
    return JsonResponse(json_dict,json_dumps_params={'ensure_ascii': False})
def ok(message='OK',data=None):
    return result(code=HttpCode.ok,message=message,data=data)
def page_error(message="",data=None):
    return result(code=HttpCode.pageerror,message=message,data=data)
def method_error(message='',data=None):
    return result(code=HttpCode.methoderror,message=message,data=data)
def server_error(message='',data=None):
    return result(code=HttpCode.servererror,message=message,data=data)

任何接口的返回结果,都是用resutful.py方法进行规整

# 短信验证码校验
def sms_check(request):
    # /duanxin/sms_check/?phone=xxx&code=xxx
    # 1. 电话和手动输入的验证码
    phone = request.GET.get('phone')
    code = request.GET.get('code')
    # 2. 获取redis中保存的code
    print('缓存中是否包含:',cache.has_key(phone))
    print('取值:',cache.get(phone))
    cache_code = cache.get(phone)
    # 3. 判断
    if code == cache_code:
        #格式统一调整后的
        return restful.ok("OK",data=None)
    else:
        #格式统一调整后的
        return restful.params_error("验证码错误", data=None)

功能6:前端短信Ajax两个

<script type="text/javascript">
            //倒计时
            var countdown=60;
            function sendemail(){
                var obj = $("#btn");
                settime(obj);
 
                }
            function settime(obj) { //发送验证码倒计时
                if (countdown == 0) {
                    obj.attr('disabled',false);
                    //obj.removeattr("disabled");
                    obj.val("免费获取验证码");
                    countdown = 60;
                    return;
                } else {
                    obj.attr('disabled',true);
                    obj.val("重新发送(" + countdown + ")");
                    countdown--;
                }
            setTimeout(function() {
                settime(obj) }
                ,1000)
            }
        </script>
     <script>
            //验证码
            $('#btn').click(function () {
                phone = $('#phone').val();
                if (phone == "") {
                    alert("请输入手机号");
                    return false;
                }
                //ajax
                $.ajax({
                    type: "get",
                    url: "/user/sms_send",
                    data: "phone="+phone,
                    success: function (msg) {
                        console.log("Data Saved: "+msg);
                        //转换为json
                        obj = eval("("+msg+")");
                        console.log('结果: '+obj.Message);
                        if (obj.Message == "OK") {
                            $('#msg').html("短信发送成功")
                        }else{
                            $('#msg').html("短信发送失败")
                        }
                    },
                    error: function (res) {
                        //状态码
                        console.log(res.status)
                    }
                });
            })
        </script>
<script>
          //短信验证码校验
            $('#smscode').change(function () {
                phone = $('#phone').val();
                code = $('#smscode').val();
                $.ajax({
                    type: "get",
                    url: "/user/sms_check",
                    data: "phone="+phone+"&code="+code,
                    success: function (msg) {
                        console.log("Data Saved: "+msg);
                        if (msg.code == '200') {
                            alert('成功');
                        }else{
                            $('#msg').html("手机验证码错误")
                        }
                    },
                    error: function (res) {
                        console.log(res.status)
                    }
                });
 
            })
        </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值