前面写了一篇客户端注册页--手机号验证--失败篇,经过很多的曲折,也想写成功篇,但是每次开始写都会发现新问题,所以前后拖的时间间隔很大,现在终于有一个有一点满意的了,特别再来写一次。
我原来的设想是在注册页中把所有信息都一次性填写完毕,但是这样写的话就会很麻烦,需要验证的数据很多,而且转念一想,我只是简单的注册一个帐号而已,对于后台只需要两个数据,一个是用户的手机号,另一个就是用户的密码了。
所以我把页面精简成这样了。
四个输入框,两个按钮,一个确认框,(别吐槽背景图片丑了,我会面会换的,现在拿来凑活的)
首先来解释几点,第一,我没有让用户输入图片验证码,因为有 thinkphp 的令牌验证,所以我不需要担心表单的重复提交。接着这里我这里只是让用户输入了手机号和密码,所以在数据库中设计需要有一点改动,很多信息都要设置默认值,这是我的客户表:
根据上表,当我们需要加入一条数据时,只需要电话号码以及密码就可以了,而且密码在传入数据库之前需要进行加密处理,不能让数据库管理人员知道客户的密码。
下面来讲具体的实现,先是 html 代码:
<div class="row" style="margin-top: 180px">
<div class="col-lg-6">
</div>
<div class="col-lg-5">
<form class="form-horizontal" role="form" action="https://www.lucifer.morning.star.com.cn/index.php/Home/register/dealWith_Form" method="post">
<div class="form-group">
<center style="font-weight:bold;color: #ff0000">{$message}</center>
</div>
<!--手机号部分-->
<div class="form-group">
<label class="col-sm-3 control-label">手机号:</label>
<div class="col-sm-6">
<!--onpropertychange="replaceNotNumber(this)" οninput="replaceNotNumber(this)"这两个函数是保证输入数据一定为数字,自定义函数,当用户输入时触发-->
<input type="tel" class="form-control" id="telephone" placeholder="请输入手机号" onpropertychange="replaceNotNumber(this)" οninput="replaceNotNumber(this)">
</div>
<div class="col-sm-3">
<!--原先设置成 hidden 属性,当使用 js 验证后出现错误就把 hidden 属性去掉-->
<span id="telephone_warning" class="glyphicon glyphicon glyphicon-info-sign hidden" style="margin-top: 5px;color: #ff0000;font-weight: bold"></span>
</div>
</div>
<!--第一次输入密码部分-->
<div class="form-group">
<label for="inputPassword3" class="col-sm-3 control-label">密码:</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="inputPassword1" placeholder="至少8位,最多11位" name="key">
</div>
<div class="col-sm-3">
<span id="password1_warning" class="glyphicon glyphicon glyphicon-info-sign hidden" style="margin-top: 5px;color: #ff0000;font-weight: bold"></span>
</div>
</div>
<!--第二次输入密码-->
<div class="form-group">
<label for="inputPassword3" class="col-sm-3 control-label">确认密码:</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="inputPassword2" placeholder="再次输入密码">
</div>
<div class="col-sm-3">
<span id="password2_warning" class="glyphicon glyphicon glyphicon-info-sign hidden" style="margin-top: 5px;color: #ff0000;font-weight: bold">与上面输入不同</span>
</div>
</div>
<!--验证码部分-->
<div class="form-group">
<button id="identifyCode" type="button" class="btn btn-primary col-lg-2 col-sm-3" style="margin-left: 50px" οnclick="identify()">获取验证码</button>
<div class="col-sm-6">
<input type="text" id="idc" class="form-control" placeholder="请输入验证码" onpropertychange="replaceNotNumber(this)" οninput="replaceNotNumber(this)" name="identifyCode">
</div>
</div>
<!--条款细节-->
<div class="form-group">
<div class="col-sm-offset-3 col-sm-10">
<div class="checkbox">
<label>
<input id="caluse" type="checkbox"><span οnclick="clause()">详细条款</span>
</label>
</div>
</div>
</div>
<!--注册按钮-->
<div class="form-group">
<div class="col-sm-offset-3 col-sm-6">
<button id="submit" type="submit" class="btn btn-primary" style="width:100%">注册</button>
</div>
</div>
</form>
</div>
</div>
结合上面的网页展示以及每个组件内部结构都是相似的,所以我直接一次性全贴出来了。(我用了 bootstrap 框架,所以想直接用的可以把编译好的框架代码导入进去就可以了)
接下来就是分开来讲 js 部分。
首先是手机号部分:
// 手机号验证,将此手机号传回后台判断此手机号是否是已注册的用户
$("#telephone").change(function () {
var telephones = $("#telephone").val();
//验证手机号位数
if (telephones.length != 11) {
$("#telephone_warning").text("无效手机号");
$("#telephone_warning").removeClass("hidden");
return false;
}
var $return = $.ajax({
type: "post",
// url_pe 全局变量,所有 url 的前缀都是一样的,所以这里设置成一样的
url: url_pe + "identify",
data: {
"telephone": telephones
},
success: function () {
// 解析后台传回数据,$return.responseText 将 $return 变成字符串形式,jQuery.parseJSON 解析 json 字符串并将其组合成数组形式返回
var $arr = jQuery.parseJSON($return.responseText);
// 此手机号正确且还没注册
if ($arr['code'] == 1) {
$("#telephone_warning").addClass("hidden");
// 这个变量在下面提交表单的时候会用到
telephone_check = true;
}
//此手机号已被注册,会显示下面的超链接提醒用户去注册,并把手机号传过去,让用户不用二次输入
else if ($arr['code'] == 2) {
$("#telephone_warning").text("");
$("#telephone_warning").append("<a href='https://www.lucifer.morning.star.com.cn/index.php/Home/admin/index/tel/"+telephones+".html'>请直接登录</a>");
$("#telephone_warning").removeClass("hidden");
}
// 当用户恶意关闭前面的 js 验证,传非法字符回后台,在后台验证失败之后会回传来显示
else {
$("#telephone_warning").text("无效手机号");
$("#telephone_warning").removeClass("hidden");
}
},
error: function () {
alert("服务器繁忙或者请检查网络链接");
}
});
});
接下来就是我的后台处理程序了,采用的是 thinkphp 3.2.3。
/**
* 验证手机号是否注册
*/
public function identify() {
$telephone = $_POST['telephone'];
//下面采用正则表达式来验证此号码是否是数字,还需要验证手机号长度是否是11位
$pattern = "/^[0-9]*$/";
if (preg_match($pattern, $telephone) == 0 || strlen($telephone) != 11) {
$data['code'] = 3;
} else {
//现在来验证是否有此手机号
$where['telephone'] = array('eq', $telephone);
$result = M("Customer")->field("telephone")->where($where)->count();
if ($result != 0) {
//表示该手机号已存在
$data['code'] = 2;
} else {
//该手机号正确
$data['code']=1;
//暂时缓存此手机号,当前台用户点击 获取验证码 的按钮之后就不需要再读取一次电话号码,
//因为读取一次就要验证一次,还不如直接在这里缓存好
$_SESSION['telephone_temp'] = $telephone;
}
}
$this->ajaxReturn($data);
}
可以看到就是很简单的验证一下该手机号是否是纯数字,是否是11位,在用户表中该手机号是否已存在。
接下来就是密码的 js 事件,更加简单,因为不需要传回后台验证密码,只需要简单的判断是否是大于8位,小于11位就行了。顺道把下面的二次输入密码也贴出来,只是判断跟上一次输入是否一致。
$("#inputPassword1").change(function () {
var pd1 = $("#inputPassword1").val();
if (pd1.length < 8) {
$("#password1_warning").text("密码至少8位");
$("#password1_warning").removeClass("hidden");
} else if (pd1.length > 11) {
$("#password1_warning").text("密码最多11位");
$("#password1_warning").removeClass("hidden");
} else {
$("#password1_warning").addClass("hidden");
pd1_store = pd1;
passwords_1 = true;
}
});
$("#inputPassword2").change(function () {
var pd2 = $("#inputPassword2").val();
if (pd2 == pd1_store) {
passwords_2 = true;
$("#password2_warning").addClass("hidden");
} else {
$("#password2_warning").removeClass("hidden");
}
});
下面就是验证码部分了。
首先是“获取验证码”的按钮,点击此按钮后,按钮文本会显示倒计时,并使用 ajax 通知后台发送短信验证。
// 点击“获取验证码”之后执行的函数
function identify() {
//上面在手机号输入框的 change 事件中当手机号输入正确这个参数才会变成 true
if (telephone_check != true) {
alert("手机号输入有误");
return false;
}
// 不需要传任何数据回后台,电话号码在后台缓存着,不需要再传一次
$return = $.ajax({
type: "post",
url: url_pe + "sendIdentifyCode",
data: null,
success: function () {
// 改变此文本的文字,显示倒计时效果,showtime()是自定义函数
countdown = 60;
showtime();
},
error: function () {
alert("服务器繁忙或者请检查网络链接");
}
});
}
function showtime() {
$button = $("#identifyCode");
//时间到,需要重新点击 “获取验证码” 来再重复一次
if (countdown == 0) {
$button.text("重新获取验证码");
$button.removeAttr("disabled");
}
// 在倒计时期间,把按钮设置成 disabled,防止用户重复点击
else {
$button.attr("disabled", true);
$button.text(countdown + "s后无效");
countdown--;
}
// 设置这个函数每 1000ms 执行1次,也就是1秒,setTimeout 一定是写在函数内部的
setTimeout(function () {
showtime()
}, 1000);
}
接下来就是后台的发送验证码操作了。
/**
* 发送验证码的操作
*/
public function sendIdentifyCode() {
if($_SESSION['telephone_temp']==null){
$this->ajaxReturn(null, 'json');
return false;
}
$telephone = $_SESSION['telephone_temp'];
// 缓存这个验证码90秒,90秒后无效,不会与其他缓存的过期时间起冲突
// identifying_code 是一个自定义的产生指定位数的随机数的自定义函数,C('IDENTIFY_CODING_LENGTH')读取
// 配置文件中的一个自定义常量 IDENTIFY_CODING_LENGTH,设置验证码的位数,后面的90是缓存时间,单位为秒
S('identify_coding', identifying_code(C('IDENTIFY_CODING_LENGTH')), 90);
//这里开始调用发送验证码的短信,着两行代码的作用看 客户端注册页--手机号码验证--失败篇
$message=new Ecd($this->url,$this->app_key,$this->app_secret,$this->format);
$message->send_sms_code($telephone,'396',S('identify_coding'));
// 这一步是重点!!!根据我们的设计,缓存用户手机号的是 $_SESSION['telephone_temp'],设想以下情况
// 用户首先使用正确的手机号验证,在获取验证码之后再来修改电话输入框中的号码,经过上面的手机号验证函数
// identify,只要这个号码是未验证过的,那么$_SESSION['telephone_temp']就改变了,如果我们最后存入数据
// 库时就存放了一个未经过验证的号码,所以这里需要在发送短信之后再设置一遍号码存储,最后存放在数据库中的
// 是$_SESSION['telephone_db'],而不是 $_SESSION['telephone_temp']
$_SESSION['telephone_db']=$telephone;
$this->ajaxReturn(null, 'json');
}
接下来在客户端不需要对用户输入的验证码做任何处理,直接传回后台处理。
下面就到了“条款细节”这部分了,这里我采用了 bootstrap 的一个弹出模拟框,当点击“条款细节”的时候会显示出下面这部分内容:
(请自动忽略其中的内容,我不会写这些玩意)
其实这部分是可以作为一个 div 来编辑的,比起 alert 可以存放更多内容,甚至可以在其中添加按钮,下来菜单等,甚至 js 事件都是可以的。
这部分的代码如下:
<!-- Modal -->
<div class="modal fade" id="myModal2" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<!--右侧的关闭按钮-->
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<!--标题-->
<h4 class="modal-title" id="myModalLabel">条款细节</h4>
</div>
<!--主体部分,我只是单纯存放了文本-->
<div class="modal-body">
“明亮之星(文中指的是巴比伦王),早晨之子啊,你何竟从天坠落?你这攻败列国的何竟被砍倒在地上?你心里曾说:我要升到天上;我要高举我的宝座在神众星以上;我要坐在聚会的山上,在北方的极处。我要升到高云之上;我要与至上者同等。然而,你必坠落阴间,到坑中极深之处。”
——《以赛亚书》<br>
路加福音第十章十八节:耶稣对他们说,我曾看见撒旦从天上坠落,像闪电一样。<br>
以赛亚书第十四章十二节:明亮之星,早晨之子,你何竟从天坠落。你这攻败列国的,何竟被砍倒在地上。<br>
以赛亚书第十四章十三节:你心里曾说,我要升到天上。我要高举我的宝座在神众星以上。我要坐在聚会的山上,在北方的极处,
以赛亚书第十四章十四节:我要升到高云之上。我要与至上者同等。<br>
启示录第十二章三节:天上又现出异象来。有一条大红龙,七头十角,七头上戴着七个冠冕。<br>
启示录第十二章四节:它的尾巴拖拉着天上星辰的三分之一,摔在地上。<br>
启示录第十二章七节: 在天上就有了争战。米迦勒同他的使者与龙争战。龙也同它的使者去争战。<br>
启示录第十二章八节:并没有得胜,天上再没有它们的地方。<br>
启示录第十二章九节:大龙就是那古蛇名叫魔鬼,又叫撒旦,是迷惑普天下的。它被摔在地上,它的使者也一同被摔下去。<br>
启示录二十章二节:他捉住那龙,就是古蛇,又叫魔鬼,也叫撒旦,把它捆绑一千年,
启示录二十章三节:扔在无底坑里,将无底坑关闭,用印封上,使它不得再迷惑列国,等到那一千年完
了。以后必须暂时释放它。<br>
启示录二十二章十六节:我耶稣差遣我的使者为众教会将这些事向你们证明。我是大卫的根,又是他的后裔。我是明亮的晨星。
</div>
<!--底部-->
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
需要事件来触发这个弹出框,这里可以看到上面的“条款细节”部分为其添加了一个 onclick 事件,在 onclick 事件中触发这个模拟弹出框。
function clause(){
$('#myModal2').modal('show');//这行代码实现弹出框的显示,至于关闭,弹出框中关闭按钮
return false;
}
最后就是表单提交按钮了,表单提交的时候还需要对表单数据进行一点修改以及数据的以及验证。
//表单提交时的事件
$("form").submit(function(){
//下面的参数只有子啊输入正确时才会被设置成 true,当输入错误的时候又会被设置为 false
if (telephone_check != true) {
alert("手机号输入有误");
return false;
}else if (passwords_1 != true || passwords_2 != true) {
alert("密码输入有误");
return false;
}else if($("#caluse").get(0).checked==false){
alert("请确保您同意我们的条款");
return false;
}
// 就是在这里将数据经过单向散列函数 md5 操作,防止数据库人员知道用户的登录密码
$("#inputPassword1").val( $.md5($("#inputPassword1").val()));
});
最后的表单后台处理程序:
/**
* 表单的处理函数
*/
public function dealWith_Form(){
// 首先先获取表单中的数据
// 验证码
$identifyCode=I("identifyCode");
// 密码
$passwords=I("key");
// 下面的情况是针对异常情况的处理,注意缓存验证码的时间过了的话,S('identify_coding')会变成 null
// message 会传到刚才的注册页面显示
if($identifyCode==null || strlen($identifyCode)!=C('IDENTIFY_CODING_LENGTH') || S('identify_coding')==null){
$this->assign("message","无效验证码");
$this->display("Index2/telephone");
return false;
}
else if($identifyCode!=S('identify_coding')){
$this->assign("message","手机号验证失败");
$this->display("Index2/telephone");
return false;
}
else if($passwords==null){
$this->assign("message","无效密码,请重新设置");
$this->display("Index2/telephone");
return false;
}
$data['telephone']=$_SESSION['telephone_db'];
$data['passwords']=$passwords;
M("Customer")->add($data);
return true;
// 下面的操作我还没想好,到这里已经将这条数据插入数据库了
}
上面一直挺乱的,我直接把全部程序贴出来,前台:
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>注册页</title>
<link href="../../../../Public/css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
<style type="text/css">
body{
background-image: url("../../../../Public/Images/background/register_bg.jpg");
background-repeat: no-repeat;
/*这样设置之后图片就会占满整个屏幕*/
background-size: 100%;
}
</style>
</head>
<body>
<div class="row" style="margin-top: 180px">
<div class="col-lg-6">
</div>
<div class="col-lg-5">
<form class="form-horizontal" role="form" action="https://www.lucifer.morning.star.com.cn/index.php/Home/register/dealWith_Form" method="post">
<div class="form-group">
<!--就是在这里显示控制器传到前台的错误信息,设置为加粗且红色-->
<center style="font-weight:bold;color: #ff0000">{$message}</center>
</div>
<!--手机号部分-->
<div class="form-group">
<label class="col-sm-3 control-label">手机号:</label>
<div class="col-sm-6">
<!--onpropertychange="replaceNotNumber(this)" οninput="replaceNotNumber(this)"这两个函数是保证输入数据一定为数字,自定义函数,当用户输入时触发-->
<input type="tel" class="form-control" id="telephone" placeholder="请输入手机号" onpropertychange="replaceNotNumber(this)" οninput="replaceNotNumber(this)">
</div>
<div class="col-sm-3">
<!--原先设置成 hidden 属性,当使用 js 验证后出现错误就把 hidden 属性去掉-->
<span id="telephone_warning" class="glyphicon glyphicon glyphicon-info-sign hidden" style="margin-top: 5px;color: #ff0000;font-weight: bold"></span>
</div>
</div>
<!--第一次输入密码部分-->
<div class="form-group">
<label for="inputPassword3" class="col-sm-3 control-label">密码:</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="inputPassword1" placeholder="至少8位,最多11位" name="key">
</div>
<div class="col-sm-3">
<span id="password1_warning" class="glyphicon glyphicon glyphicon-info-sign hidden" style="margin-top: 5px;color: #ff0000;font-weight: bold"></span>
</div>
</div>
<!--第二次输入密码-->
<div class="form-group">
<label for="inputPassword3" class="col-sm-3 control-label">确认密码:</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="inputPassword2" placeholder="再次输入密码">
</div>
<div class="col-sm-3">
<span id="password2_warning" class="glyphicon glyphicon glyphicon-info-sign hidden" style="margin-top: 5px;color: #ff0000;font-weight: bold">与上面输入不同</span>
</div>
</div>
<!--验证码部分-->
<div class="form-group">
<button id="identifyCode" type="button" class="btn btn-primary col-lg-2 col-sm-3" style="margin-left: 50px" οnclick="identify()">获取验证码</button>
<div class="col-sm-6">
<input type="text" id="idc" class="form-control" placeholder="请输入验证码" onpropertychange="replaceNotNumber(this)" οninput="replaceNotNumber(this)" name="identifyCode">
</div>
</div>
<!--条款细节-->
<div class="form-group">
<div class="col-sm-offset-3 col-sm-10">
<div class="checkbox">
<label>
<input id="caluse" type="checkbox"><span οnclick="clause()">详细条款</span>
</label>
</div>
</div>
</div>
<!--注册按钮-->
<div class="form-group">
<div class="col-sm-offset-3 col-sm-6">
<button id="submit" type="submit" class="btn btn-primary" style="width:100%">注册</button>
</div>
</div>
</form>
</div>
</div>
<!--下面使用 bootstrap 模拟弹出框,就是当点击 条款细节 之后会弹出的部分-->
<!-- Modal -->
<div class="modal fade" id="myModal2" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<!--右侧的关闭按钮-->
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<!--标题-->
<h4 class="modal-title" id="myModalLabel">条款细节</h4>
</div>
<!--主体部分,我只是单纯存放了文本-->
<div class="modal-body">
“明亮之星(文中指的是巴比伦王),早晨之子啊,你何竟从天坠落?你这攻败列国的何竟被砍倒在地上?你心里曾说:我要升到天上;我要高举我的宝座在神众星以上;我要坐在聚会的山上,在北方的极处。我要升到高云之上;我要与至上者同等。然而,你必坠落阴间,到坑中极深之处。”
——《以赛亚书》<br>
路加福音第十章十八节:耶稣对他们说,我曾看见撒旦从天上坠落,像闪电一样。<br>
以赛亚书第十四章十二节:明亮之星,早晨之子,你何竟从天坠落。你这攻败列国的,何竟被砍倒在地上。<br>
以赛亚书第十四章十三节:你心里曾说,我要升到天上。我要高举我的宝座在神众星以上。我要坐在聚会的山上,在北方的极处,
以赛亚书第十四章十四节:我要升到高云之上。我要与至上者同等。<br>
启示录第十二章三节:天上又现出异象来。有一条大红龙,七头十角,七头上戴着七个冠冕。<br>
启示录第十二章四节:它的尾巴拖拉着天上星辰的三分之一,摔在地上。<br>
启示录第十二章七节: 在天上就有了争战。米迦勒同他的使者与龙争战。龙也同它的使者去争战。<br>
启示录第十二章八节:并没有得胜,天上再没有它们的地方。<br>
启示录第十二章九节:大龙就是那古蛇名叫魔鬼,又叫撒旦,是迷惑普天下的。它被摔在地上,它的使者也一同被摔下去。<br>
启示录二十章二节:他捉住那龙,就是古蛇,又叫魔鬼,也叫撒旦,把它捆绑一千年,
启示录二十章三节:扔在无底坑里,将无底坑关闭,用印封上,使它不得再迷惑列国,等到那一千年完
了。以后必须暂时释放它。<br>
启示录二十二章十六节:我耶稣差遣我的使者为众教会将这些事向你们证明。我是大卫的根,又是他的后裔。我是明亮的晨星。
</div>
<!--底部-->
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
<script src="../../../../Public/Js/jquery-3.1.0.min.js" type="text/javascript"></script>
<script src="../../../../Public/Js/bootstrap.min.js" type="text/javascript"></script>
<script src="../../../../Public/Js/register.js" type="text/javascript"></script>
<script src="../../../../Public/Js/jquery.md5.js" type="text/javascript"></script>
<script type="text/javascript">
var url_pe = "https://www.lucifer.morning.star.com.cn/index.php/Home/register/";
var telephone_check = false;
var passwords_1 = false;
var pd1_store = null;
var passwords_2 = false;
var idc_check=null;
var countdown = 60;
// 手机号验证,将此手机号传回后台判断此手机号是否是已注册的用户
$("#telephone").change(function () {
var telephones = $("#telephone").val();
//验证手机号位数
if (telephones.length != 11) {
$("#telephone_warning").text("无效手机号");
$("#telephone_warning").removeClass("hidden");
return false;
}
var $return = $.ajax({
type: "post",
// url_pe 全局变量,所有 url 的前缀都是一样的,所以这里设置成一样的
url: url_pe + "identify",
data: {
"telephone": telephones
},
success: function () {
// 解析后台传回数据,$return.responseText 将 $return 变成字符串形式,jQuery.parseJSON 解析 json 字符串并将其组合成数组形式返回
var $arr = jQuery.parseJSON($return.responseText);
// 此手机号正确且还没注册
if ($arr['code'] == 1) {
$("#telephone_warning").addClass("hidden");
// 这个变量在下面提交表单的时候会用到
telephone_check = true;
}
//此手机号已被注册,会显示下面的超链接提醒用户去注册,并把手机号传过去,让用户不用二次输入
else if ($arr['code'] == 2) {
$("#telephone_warning").text("");
$("#telephone_warning").append("<a href='https://www.lucifer.morning.star.com.cn/index.php/Home/admin/index/tel/"+telephones+".html'>请直接登录</a>");
$("#telephone_warning").removeClass("hidden");
telephone_check=false;
}
// 当用户恶意关闭前面的 js 验证,传非法字符回后台,在后台验证失败之后会回传来显示
else {
$("#telephone_warning").text("无效手机号");
$("#telephone_warning").removeClass("hidden");
telephone_check=false;
}
},
error: function () {
alert("服务器繁忙或者请检查网络链接");
}
});
});
// 第一次输入密码时判断是否在8到11位之间
$("#inputPassword1").change(function () {
var pd1 = $("#inputPassword1").val();
if (pd1.length < 8) {
$("#password1_warning").text("密码至少8位");
$("#password1_warning").removeClass("hidden");
passwords_1=false;
} else if (pd1.length > 11) {
$("#password1_warning").text("密码最多11位");
$("#password1_warning").removeClass("hidden");
passwords_1=false;
} else {
$("#password1_warning").addClass("hidden");
pd1_store = pd1;
passwords_1 = true;
}
});
// 判断是否跟上次输入一致
$("#inputPassword2").change(function () {
var pd2 = $("#inputPassword2").val();
if (pd2 == pd1_store) {
passwords_2 = true;
$("#password2_warning").addClass("hidden");
} else {
$("#password2_warning").removeClass("hidden");
passwords_2=false;
}
});
//表单提交时的事件
$("form").submit(function(){
//下面的参数只有子啊输入正确时才会被设置成 true,当输入错误的时候又会被设置为 false
if (telephone_check != true) {
alert("手机号输入有误");
return false;
}else if (passwords_1 != true || passwords_2 != true) {
alert("密码输入有误");
return false;
}else if($("#caluse").get(0).checked==false){
alert("请确保您同意我们的条款");
return false;
}
// 就是在这里将数据经过单向散列函数 md5 操作,防止数据库人员知道用户的登录密码
$("#inputPassword1").val( $.md5($("#inputPassword1").val()));
});
</script>
<script type="text/javascript">
// 点击“获取验证码”之后执行的函数
function identify() {
//上面在手机号输入框的 change 事件中当手机号输入正确这个参数才会变成 true
if (telephone_check != true) {
alert("手机号输入有误");
return false;
}
// 不需要传任何数据回后台,电话号码在后台缓存着,不需要再传一次
$return = $.ajax({
type: "post",
url: url_pe + "sendIdentifyCode",
data: null,
success: function () {
// 改变此文本的文字,显示倒计时效果,showtime()是自定义函数
countdown = 60;
showtime();
},
error: function () {
alert("服务器繁忙或者请检查网络链接");
}
});
}
function showtime() {
$button = $("#identifyCode");
//时间到,需要重新点击 “获取验证码” 来再重复一次
if (countdown == 0) {
$button.text("重新获取验证码");
$button.removeAttr("disabled");
}
// 在倒计时期间,把按钮设置成 disabled,防止用户重复点击
else {
$button.attr("disabled", true);
$button.text(countdown + "s后无效");
countdown--;
}
// 设置这个函数每 1000ms 执行1次,也就是1秒,setTimeout 一定是写在函数内部的
setTimeout(function () {
showtime()
}, 1000);
}
function clause(){
$('#myModal2').modal('show');
return false;
}
</script>
</body>
</html>
后台处理程序:
<script type="text/javascript">
</script>
<?php
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
namespace Home\Controller;
use Think\Controller;
class RegisterController extends Controller {
private $url = "http://www.etuocloud.com/gatetest.action";
private $app_key = '这玩意我是不会贴出来了';
private $app_secret = '这个也是';
private $format = 'xml';
/**
* 就是简单的跳转到最基础的注册页
*/
public function index() {
$this->display("Index2/telephone");
}
/**
* 验证手机号是否注册
*/
public function identify() {
$telephone = $_POST['telephone'];
//下面采用正则表达式来验证此号码是否是数字,还需要验证手机号长度是否是11位
$pattern = "/^[0-9]*$/";
if (preg_match($pattern, $telephone) == 0 || strlen($telephone) != 11) {
$data['code'] = 3;
} else {
//现在来验证是否有此手机号
$where['telephone'] = array('eq', $telephone);
$result = M("Customer")->field("telephone")->where($where)->count();
if ($result != 0) {
//表示该手机号已存在
$data['code'] = 2;
} else {
//该手机号正确
$data['code']=1;
//暂时缓存此手机号,当前台用户点击 获取验证码 的按钮之后就不需要再读取一次电话号码,
//因为读取一次就要验证一次,还不如直接在这里缓存好
$_SESSION['telephone_temp'] = $telephone;
}
}
$this->ajaxReturn($data);
}
/**
* 发送验证码的操作
*/
public function sendIdentifyCode() {
if($_SESSION['telephone_temp']==null){
$this->ajaxReturn(null, 'json');
return false;
}
$telephone = $_SESSION['telephone_temp'];
// 缓存这个验证码90秒,90秒后无效,不会与其他缓存的过期时间起冲突
// identifying_code 是一个自定义的产生指定位数的随机数的自定义函数,C('IDENTIFY_CODING_LENGTH')读取
// 配置文件中的一个自定义常量 IDENTIFY_CODING_LENGTH,设置验证码的位数,后面的90是缓存时间,单位为秒
S('identify_coding', identifying_code(C('IDENTIFY_CODING_LENGTH')), 90);
//这里开始调用发送验证码的短信
//$message=new Ecd($this->url,$this->app_key,$this->app_secret,$this->format);
//$message->send_sms_code($telephone,'396',S('identify_coding'));
// 这一步是重点!!!根据我们的设计,缓存用户手机号的是 $_SESSION['telephone_temp'],设想以下情况
// 用户首先使用正确的手机号验证,在获取验证码之后再来修改电话输入框中的号码,经过上面的手机号验证函数
// identify,只要这个号码是未验证过的,那么$_SESSION['telephone_temp']就改变了,如果我们最后存入数据
// 库时就存放了一个未经过验证的号码,所以这里需要在发送短信之后再设置一遍号码存储,最后存放在数据库中的
// 是$_SESSION['telephone_db'],而不是 $_SESSION['telephone_temp']
$_SESSION['telephone_db']=$telephone;
$this->ajaxReturn(null, 'json');
}
/**
* 表单的处理函数
*/
public function dealWith_Form(){
// 首先先获取表单中的数据
// 验证码
$identifyCode=I("identifyCode");
// 密码
$passwords=I("key");
// 下面的情况是针对异常情况的处理,注意缓存验证码的时间过了的话,S('identify_coding')会变成 null
// message 会传到刚才的注册页面显示
if($identifyCode==null || strlen($identifyCode)!=C('IDENTIFY_CODING_LENGTH') || S('identify_coding')==null){
$this->assign("message","无效验证码");
$this->display("Index2/telephone");
return false;
}
else if($identifyCode!=S('identify_coding')){
$this->assign("message","手机号验证失败");
$this->display("Index2/telephone");
return false;
}
else if($passwords==null){
$this->assign("message","无效密码,请重新设置");
$this->display("Index2/telephone");
return false;
}
$data['telephone']=$_SESSION['telephone_db'];
$data['passwords']=$passwords;
M("Customer")->add($data);
return true;
//
}
}
还有一些杂的 js 函数。
//确保输入为数字
function replaceNotNumber()
{
var pattern = /[^0-9]/g;
if (pattern.test(hehe.value))
{
hehe.value = hehe.value.replace(pattern, "");
}
}
还有很多一个 md5 的 js 库,自己去找吧,或者哪一天我会用 github
把全部资源上传上去。