• 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,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>
    

       

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

  • 相关阅读:
    shell编程
    git
    Flask-SQLAlchemy
    pipreqs
    命令行操作flask
    SQLAlchemy中scoped_session实现线程安全
    打印信息
    键盘事件
    安卓手机APP压力monkey测试
    手机APP功能测试经验分享2016.06.06
  • 原文地址:https://www.cnblogs.com/zmdComeOn/p/12115412.html
Copyright © 2020-2023  润新知