django-实现登录短信验证

功能演示

 

 

 

核心任务

  • 前端功能:
  1. 点击按钮Ajax调用发送验证码功能
  2. 输完验证码后Ajax调用验证功能
  • 后端功能:
  1. 功能1:发送验证码功能
  2. 功能2:验证码检查
  • 后台核心逻辑(不需要手写)
  1. 功能3:发短信
  2. 功能4:生成短信验证码(随机生成6位数字)
  • 集成Redis
  1. 使用Redis代替session缓存,存储数据!
  2. Redis集成到Django中!
  • 扩展功能:
  1. 统一接口返回结果的规范方法!

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

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


第一步: 下载django-redis模块

 

pip install django-redis

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

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

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

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

from django.core.cache import cache

第四步: 使用

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

 

功能2: 短信下发

第一步: 申请短信服务

参考文档 申请阿里云短信服务.pdf文档

第二步: 独立发送短信和生成验证码的模块

#!/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','znxNezmm4zfA9kPyqx1WrpznjCaJFT','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: 统一接口的数据格式:
独立restful.py 接口模块!
参考:
https://blog.csdn.net/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,data=data)
def method_error(message='',data=None):
	return result(code=HttpCode.methoderror,data=data)
def server_error(message='',data=None):
	return result(code=HttpCode.servererror,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.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>

   

转载自:https://blog.csdn.net/Babysbreath_JTC/article/details/89319048

原文地址:https://www.cnblogs.com/zmdComeOn

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


注:所有源代码均实测运行过。所有源代码均已上传CSDN,请有需要的朋友自行下载。
继承APIView和ViewSetMixin;作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。ViewSet在开发接口中不经常用。
一、Django介绍Python下有许多款不同的 Web 框架。Django是重量级选手中最有代表性的一位。许多成功的网站和APP都基于Django。Django 是一个开放源代码的 Web 应用框架,由 Python 写成。Django 遵守 BSD 版权,初次发布于 2005 年 7 月, 并于 2008 年 9 月发布了第一个正式版本 1.0 。Django学习线路Django 采用了 MVT 的软件设计模式,即模型(Model),视图(View)和模板(Template)。这个MVT模式并
本文从nginx快速掌握到使用,gunicorn快速掌握到使用,实现小白快速搭建django项目,并对可能出现的报错进行了分析
uniapp微信小程序订阅消息发送服务通知
Django终端打印SQL语句 1 Setting配置: 2 默认python 使用的MysqlDB连接,Python3 支持支持pymysql 所有需要在app里面的__init__加上下面配置:
url: re_path(&#39;authors/$&#39;, views.AuthorView.as_view()), re_path(&#39;book/(?P\d+)/$&#39;, vie
前提 关于html寻找路线: template 如果在各个APP中存在, Django 会优先找全局template 文件下的html文件,如果全局下的template文件没有相关的html Djan
// GET请求request.GET // POST请求request.POST // 处理文件上传请求request.FILES // 处理如checkbox等多选 接受列表request.get
from bs4 import BeautifulSoup#kindeditordef kindeditor(request): s = &#39;&#39;&#39; &lt;li&gt;&lt;s
view.py 配置 html 配置
from django.http import JsonResponse JsonResponse 里面代码会加这一个响应头 kwargs.setdefault(&#39;content_type&#
#下面两种是基于QuerySet查询 也就是说SQL中用的jion连表的方式查询books = models.UserInfo.objects.all() print(type(books)) &gt
return HttpResponse(&quot;OK&quot;) 返回一个字符串 return redirect(&quot;/index/&quot;) 返回URL return render
from django.http import JsonResponse JsonResponse 里面代码会加这一个响应头 kwargs.setdefault(&#39;content_type&#
浏览器有一个很重要的概念——同源策略(Same-Origin Policy)。所谓同源是指,域名,协议,端口相同。不同源的客户端脚本(javascript、ActionScript)在没明确授权的情况
自动发送 &gt; 依赖jQuery文件 实例--&gt;GET请求: 手动发送 &gt; 依赖浏览器XML对象(也叫原生ajax) Ajax主要就是使用 【XmlHttpRequest】对象来完成请
#下面两种是基于QuerySet查询 也就是说SQL中用的jion连表的方式查询books = models.UserInfo.objects.all() print(type(books)) &gt
// GET请求request.GET // POST请求request.POST // 处理文件上传请求request.FILES // 处理如checkbox等多选 接受列表request.get
return HttpResponse(&quot;OK&quot;) 返回一个字符串 return redirect(&quot;/index/&quot;) 返回URL return render