短信验证码登录功能
- 项目分析
- 核心代码
- 1.外部js库调用
- 2.HTML容器构建
- 3.javaScript业务逻辑验证
- 4.后端验证逻辑
- 总结
短信验证码是通过发送验证码到手机的一种有效的验证码系统,作为比较准确和安全地保证购物的安全性,验证用户的正确性的一种手段,几乎网站登录都会使用该方式。
其特点是依据某些验证码接入商提供手机短信验证码服务,各网站通过接口发送请求到接入商的服务器,服务器发送随机数字或字母到手机中,由接入商的服务器统一做验证码的验证。
项目分析
- 开通阿里云、腾讯云等短信API端口;
- 为防止机器批量发送验证码,设置机器识别码,设置5分钟内发送的次数,进而予以限流;
- 发送信息错误时,进行明确的信息提示;
- 完成信息验证,执行业务正常逻辑;
核心代码
1.外部js库调用
<script type="text/javascript" src="static/js/jquery.min.js"></script>
<!--layui封装库-->
<script src="static/layui/layui.js" charset="utf-8"></script>
<link rel="stylesheet" href="static/layui/css/layui.css">
2.HTML容器构建
<div style="margin-top: 10px;padding: 20px;">
<form class="layui-form layui-form-pane">
<div class="layui-form-item">
<label for="L_user_phone" class="layui-form-label">手机号码</label>
<div class="layui-input-inline"><input type="text" id="L_user_phone" name="user_phone" class="layui-input" lay-verify="user_phone"></div>
<div class="layui-form-mid layui-word-aux"><span class="x-red">* 手机号码,作为登录账户唯一凭证,如:13500000001。</span></div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">识别码</label>
<div class="layui-input-inline"><input type="text" name="captcha" id="captcha" lay-verify="required" autocomplete="off" class="layui-input"></div>
<div class="layui-form-mid layui-word-aux"> <img src="?m=Login&a=loginDeal&act=getCode" id="getCode" alt="" title="点击刷新验证码" style="cursor: pointer;"><span class="x-red"> * </span> 发送手机短信验证</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">短信验证码</label>
<div class="layui-input-inline"><input type="text" name="smscode" id="smscode" lay-verify="smscode" autocomplete="off" class="layui-input" disabled="disabled"></div>
<div class="layui-input-inline">
<input type="button" class="layui-btn layui-btn-primary" id="btnSendCode" disabled="disabled" value="获取验证码">
</div>
</div>
<div class="layui-form-item">
<button class="layui-btn layui-btn-fluid layui-btn-normal" lay-filter="save" id="L_add" lay-submit=""> 确认登录 </button>
</div>
</form>
</div>
3.javaScript业务逻辑验证
- 验证手机号和短信验证码规则
//自定义验证规则
form.verify({
user_phone: [/^1[3|4|5|6|7|8|9]\d{9}$/, '手机必须11位,只能是数字!']
, smscode: [/[\S]+/, "验证码为6位数且5分钟内有效"]
});
- 机器识别码验证
获取实际图片识别码
$("#getCode").click(function () {
$(this).attr("src", '?m=Login&a=loginDeal&act=getCode&' + Math.random());
});
- 发送短信验证码倒计时60秒
var wait = 60;
function time(o) {
if (wait == 0) {
o.removeAttribute("disabled");
o.value = "获取验证码";
wait = 60;
} else {
o.setAttribute("disabled", true);
o.value = "重新发送(" + wait + ")";
wait--;
setTimeout(function () {
time(o);
}, 1000);
}
}
- 获取识别码和验证码的业务逻辑
//单击发送验证码;
document.getElementById("btnSendCode").onclick = function () {
var captcha = $("#captcha").val();
//获取识别码;
$.getJSON("?m=Login&a=loginDeal&act=captcha", {mobile: mobile, captcha: captcha}, function (res) {
if (res.code == '0') {
layer.msg(res.msg, {icon: 1, time: 2000});
} else {
if (wait != 60) {
layer.alert("请" + wait + "秒后再试!", {icon: 3, time: 2000})
return;
}
time(document.getElementById("btnSendCode"));
$.getJSON("?m=Sms&a=smsDeal&act=verify", {
mobile: mobile,
captcha: captcha
}, function (res2) {
//console.log(res2.send.Code);
if (res2.send.Code != "OK") {
layer.alert("短信限流,请等待5分钟", {icon: 3, time: 2000})
}
});
}
});
}
针对不同平台的业务逻辑,对返回的短信参数进行输出,提示用户操作。
if (res2.send.Code != "OK") {
layer.alert("短信限流,请等待5分钟", {icon: 3, time: 2000})
}
- 执行业务正常逻辑
//监听提交;
form.on('submit(save)', function () {
$.ajax({
type: "post",
url: "?m=Login&a=loginDeal&act=smsCode",
async: true,
data: {
user_phone: $('#L_user_phone').val(),
smscode: $('#smscode').val()
},
dataType: "json",
success: function (res) {
//console.log(res);
if (res.code == 0) {
layer.msg(res.msg, {icon: 1, time: 2000});
} else {
layer.msg(res.msg, {icon: 1, time: 2000}, function () {
var index = parent.layer.getFrameIndex(window.name);
parent.layer.close(index);
window.parent.location.href = "?m=Index&a=my";
});
}
},
error: function (err) {
console.log(err);
}
});
return false;
});
4.后端验证逻辑
- 生成随机机器识别码
case "getCode";
require_once "libs/vcode.class.php";
$obj = new vcode();//实例化;
$_SESSION['authcode'] = $obj->authcode;
die($obj->output());
break;
- 验证机器识别码
//网站识别码;
case "captcha";
$user_phone = get_param('mobile');
$captcha = isset($_GET["captcha"]) ? trim($_GET["captcha"]) : '';
if ($captcha != $_SESSION['authcode']) {
$res['code'] = "0";
$res['msg'] = "识别码错误";
die(json_encode_lockdata($res));
} else {
$res['code'] = "1";
$res['msg'] = "识别码通过";
//验证码自动销毁;
session_destroy();
die(json_encode_lockdata($res));
}
break;
- 发送短信流(次数)判断
case "verify";
require "libs/api_demo/SmsDemo.php";/*阿里云短信SDK*/
$rmdCode = rand(111111, 999999);//随机验证码
$templateCode = 'SMS_165690909';//调用模版
$signName = '言医';//签名
$mobile = get_param('mobile');//手机号
if ($mobile == "") {
die("越权访问!");
}
//增加记录;
addlogs($mobile, 'smscode', '', time(), getip());
//读取数据库记录;
$fromTime = time() - 300;
$toTime = time();
$sql = "select log_id FROM " . $db->table('log') . " WHERE 1";
$sql .= " AND logs = 'smscode' AND log_ip ='" . getip() . "'";
$sql .= " AND log_time > " . $fromTime . " AND log_time <" . $toTime . "";
$sql .= " ORDER BY log_id DESC";
$row = $db->queryall($sql);
if (count($row) >= 5) {
$res['code'] = 0;
$res['msg'] = '5分钟内最多发送5次短信.';
$res['total'] = count($row);
die(json_encode_lockdata($res));
} else {
$send = SmsDemo::sendSms($mobile, $signName, $templateCode, $rmdCode, '', '', '', '', 1);
$res['code'] = 1;
$res['send'] = $send;
$_SESSION['code'] = $rmdCode;
die(json_encode_lockdata($res));
}
break;
总结
一个简单的手机短信验证码登录,涉及到的方方面面比较多。在发送短信次数的限制上,本系统作为正常的业务逻辑进行判断和限流,同时对于阿里云和腾讯云也有对应的限制规则,需要在平台上进行设置。
@漏刻有时