功能演示

核心任務
- 前端功能:
- 點擊按鈕Ajax調用發送驗證碼功能
- 輸完驗證碼后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
#配置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
