悠悠楠杉
网站页面
正文:
在电商系统的用户注册流程中,短信验证码已成为标配的安全验证手段。今天我们就来深度剖析如何在Django商城项目中实现一套完整的短信验证码功能。
整体流程:
技术选型:
首先需要在云片官网注册账号并获取API_KEY:
# settings.py
YP_API_KEY = "your_api_key_here"
YP_SIGN = "【愚公商城】" # 审核通过的签名
# utils/sms.py
import random
import redis
from django.conf import settings
def generate_code(length=6):
"""生成指定位数的数字验证码"""
return ''.join(random.choice('0123456789') for _ in range(length))
class SMSUtil:
def __init__(self):
self.redis = redis.StrictRedis(
host=settings.REDIS_HOST,
port=settings.REDIS_PORT,
db=settings.REDIS_DB
)
def save_code(self, phone, code, expire=300):
"""保存验证码到Redis,5分钟有效期"""
key = f"sms_code:{phone}"
self.redis.setex(key, expire, code)
def check_code(self, phone, code):
"""校验验证码"""
key = f"sms_code:{phone}"
stored_code = self.redis.get(key)
return stored_code and stored_code.decode() == code
# views.py
from django.http import JsonResponse
from utils.sms import SMSUtil, generate_code
import requests
def send_sms_code(request):
if request.method != 'POST':
return JsonResponse({'status': 'error', 'msg': '请求方法错误'})
phone = request.POST.get('phone')
if not phone or len(phone) != 11:
return JsonResponse({'status': 'error', 'msg': '手机号格式错误'})
# 生成6位验证码
code = generate_code(6)
# 调用云片API发送短信
params = {
'apikey': settings.YP_API_KEY,
'mobile': phone,
'text': f'您的验证码是{code}。如非本人操作,请忽略本短信',
}
try:
resp = requests.post('https://sms.yunpian.com/v2/sms/single_send.json', data=params)
result = resp.json()
if result.get('code') == 0:
# 发送成功,保存到Redis
sms_util = SMSUtil()
sms_util.save_code(phone, code)
return JsonResponse({'status': 'success'})
else:
return JsonResponse({'status': 'error', 'msg': result.get('msg')})
except Exception as e:
return JsonResponse({'status': 'error', 'msg': str(e)})
<!-- templates/register.html -->
<div class="form-group">
<label for="phone">手机号</label>
<div class="input-group">
<input type="text" id="phone" name="phone" class="form-control">
<span class="input-group-btn">
<button id="getCodeBtn" class="btn btn-default" type="button">获取验证码</button>
</span>
</div>
</div>
<div class="form-group">
<label for="code">验证码</label>
<input type="text" id="code" name="code" class="form-control">
</div>
// static/js/register.js
$(function() {
let countdown = 60;
let timer = null;
$('#getCodeBtn').click(function() {
const phone = $('#phone').val();
if (!/^1[3-9]\d{9}$/.test(phone)) {
alert('请输入正确的手机号');
return;
}
// 禁用按钮,防止重复点击
$(this).attr('disabled', true);
$.ajax({
url: '/send_sms_code/',
type: 'POST',
data: {phone: phone},
success: function(res) {
if (res.status === 'success') {
// 开始倒计时
timer = setInterval(function() {
countdown--;
$('#getCodeBtn').text(`${countdown}秒后重新获取`);
if (countdown <= 0) {
clearInterval(timer);
$('#getCodeBtn').text('获取验证码').attr('disabled', false);
countdown = 60;
}
}, 1000);
} else {
alert(res.msg);
$('#getCodeBtn').attr('disabled', false);
}
},
error: function() {
alert('网络错误,请重试');
$('#getCodeBtn').attr('disabled', false);
}
});
});
});
频率限制:
防刷策略:
验证码失效机制:
短信延迟问题:
多设备登录冲突:
国际化支持:
通过以上完整实现,我们的Django商城项目已经具备了一套稳定可靠的短信验证码系统。在实际项目中,还可以考虑加入Celery异步任务队列来进一步提升用户体验,避免网络延迟导致的界面卡顿。