通过清心醉

自写小论坛更新: 增加邮件申请密码找回功能

#VER 2.0 htdocs
更新功能:
1:增加邮件找回密码功能,同时修改注册邮箱为唯一参数;
2:增加过滤函数,用户可自定过滤的文字,下次改版将修改为MYSQL保存敏感字符,因为放在TXT文件可被直接访问.
而且如果放PHP文件里修改比较麻烦.

首先增加两个表:
forgotpassword //找回密码数据表
adminforgotpassword //SMTP服务器连接参数 //忘记把表名取名SMTP了,不管了先

adminforgotpassword表字段包含:
ID,SMTP服务器,SMTP端口,SMTP邮箱,SMTP用户(部分可能就是邮箱),SMTP用户密码

forgotpassword表字段包含:
ID,需要找回密码的EMAIL,验证码RANDID,找回时间:TIME,操作IP

首先说说后端设置SMTP服务器::
admin_shell_table()函数里增加一个操作选择.
<td><a href=”admin_shell.php?adminshellid=5″>SMTP管理</a></td>
这里可以看到,GET请求到admin_shell.php并且adminshellid的参数为5

我们来看admin_shell.php:
case 5: //进入SMTP管理
$shell=$bbs_system->admin_smtp(); //调用了ADMIN_SMTP函数,其实就是一个表单
/**********SMTP控制实现**********/
function admin_smtp()
{
$smtp=”SELECT *FROM adminforgotpassword”;
$tempsmtp=mysql_query($smtp);
while($row=mysql_fetch_object($tempsmtp))
{
?>
<div class=”contacts”>
<form method=”post” action=””>
<table>
<tr>
<td>SMTP服务器:</td>
<td><input name=”smtpserver” type=”text” size=”30″ maxlength=”500″ value=”<?php echo $row->smtpserver;?>”></td>
</tr>
<tr>
<td>SMTP端口:</td>
<td><input name=”smtpserverport” type=”text” size=”30″ maxlength=”500″ value=”<?php echo $row->smtpserverport;?>”></td>
</tr>
<tr>
<td>SMTP邮箱:</td>
<td><input name=”smtpusermail” type=”text” size=”30″ maxlength=”500″ value=”<?php echo $row->smtpusermail;?>”></td>
</tr>
<tr>
<td>SMTP用户(可为邮箱):</td>
<td><input name=”smtpuser” type=”text” size=”30″ maxlength=”500″ value=”<?php echo $row->smtpuser;?>”></td>
</tr>
<tr>
<td>SMTP密码:</td>
<td><input name=”smtppass” type=”password” size=”30″ maxlength=”500″ value=”<?php echo $row->smtppass;?>”></td>
</tr>
</table>
<div align=”center”><input type=”submit” name=”admin_smtp” value=”修改”></div>
</form>
<?php
}
}
因为这时候我们是在admin_shell.php把表单调用了出来,所以当填写了之后,POST的数据在admin_shell.php文件里再一次提取
if(isset($_POST[“admin_smtp”])&&isset($_POST[“admin_smtp”])) //接收的如果是admin_smtp函数
{
$smtppost=array($_POST[“smtpserver”],$_POST[“smtpserverport”],$_POST[“smtpusermail”],$_POST[“smtpuser”],$_POST[“smtppass”]); //数组化SMTP的所有参数
$filtration->filtration($smtppost); //判断是否存在过滤字符
$bbs_system->textlong($smtppost); //判断所有参数的长度.
$bbs_system->mailtype($_POST[“smtpusermail”]); //独立判断邮箱格式//用户名也可以为邮箱,暂不做判断了.
$bbs_system->admin_smtp_sql($_POST[“smtpserver”],$_POST[“smtpserverport”],$_POST[“smtpusermail”],$_POST[“smtpuser”],$_POST[“smtppass”]);//传值 //其实SMTP应该放一个文件里,但懒的改了.
}
在这里我们主要看看admin_smtp_sql函数,前面的几个只是判断的函数,具体的可在CLASS.PHP文件里查看.
function admin_smtp_sql($smtpserver,$smtpport,$smtpmail,$smtpuser,$smtppass)
{ //接受SMTP数据
$server=$smtpserver;$port=$smtpport;$mail=$smtpmail;
$user=$smtpuser;$pass=$smtppass;
$sql=”UPDATE adminforgotpassword SET smtpserver=’$server’,smtpserverport=’$port’,smtpusermail=’$mail’,smtpuser=’$user’,smtppass=’$pass'”;
mysql_query($sql);
echo “<script language=\”JavaScript\”>alert(\”修改成功\”);</script>”;
echo “<script>setTimeout(\”this.location=’admin_shell.php?adminshellid=5’\”,0);</script>”;
}
至于更多判断端口是否为25,465等等,只需要自己写个小函数然后对POST的参数判断是否放行就可以了,
作者就不再一一写出,当然,后期会加上.

这样一来,后端修改SMTP服务参数的后端控方法就有了
我们再来看看前端,当用户在登陆的时候忘记了密码,点找回密码
会跳转到forgot_password.php文件.

 

<?php

//首先肯定是要判断有无$_POST的数据,如果存在这3个参数,表示用户是在修改新密码,(已获取验证代码)

if(isset($_POST[“email”])&&!empty($_POST[“email”])&&isset($_POST[“randid”])&&!empty($_POST[“randid”])&&isset($_POST[“newpassword”])&&!empty($_POST[“newpassword”])) //如果存在以上3个参数表示为忘记密码修改.
{
$textlong1=array($_POST[“email”],$_POST[“randid”],$_POST[“newpassword”]); //数组化
$filtration->filtration($textlong1);//判断是否包含非法文字
$bbs_system->mailtype($_POST[“email”]); //单一验证email格式
$bbs_system->textlong($textlong1); //把数组传递给textlong函数判断字符是否过长
//本想在该函数里返回数组给其他函数执行判断的,但考虑文本还是留给其他文本判断吧,
$bbs_system->email_password($_POST[“email”],$_POST[“randid”],$_POST[“newpassword”]);
//把过滤了非法文字和验证邮箱格式的3个POST参数交给email_password函数处理.
}

if(isset($_POST[“email”])&&!empty($_POST[“email”])&&!isset($_POST[“randid”])) //否则获取验证代码.
{
//如果只有一个EMAIL的参数,因为上面也会有,避免被调用出来,所以判断必须没有RANDID的验证码
$forgotpassword=array($_POST[“email”],$_POST[“submit”]);
$bbs_system->mailtype($_POST[“email”]); //单一验证email格式
$filtration->filtration($forgotpassword); //验证是否包含非法文字
$emailrand=$bbs_forgotpassword->forgotpass($_POST[“email”]); //获取邮箱数据库验证的随机验证码
echo “<script>setTimeout(\”this.location=’index.php’\”,0);</script>”;
}
else
{
//如果以上两条件不存在,输出表单
?>
<form method=”post” action=””>
<table width=”400″ align=”center”>
<tr>
<td>如果没有验证码请先输入您的邮箱::</td>
<td><input name=”email” type=”text” size=”30″ maxlength=”500″></td>
</tr>
</table>
<div align=”center”><input type=”submit” name=”submit” value=”获取验证码”></div>
</table>
</form>

</br></br></br>
<form method=”post” action=””>
<table width=”400″ align=”center”>
<tr><td>如果有验证码请在以下表单填写(暂时不进行代码简写了.)</td></tr>
<tr>
<td>请输入您的邮箱::</td>
<td><input name=”email” type=”text” size=”30″ maxlength=”500″></td>
</tr>
<tr>
<td>请输入您的验证码::</td>
<td><input name=”randid” type=”text” size=”30″ maxlength=”500″></td>
</tr>
<tr>
<td>请输入您的新密码::</td>
<td><input name=”newpassword” type=”text” size=”30″ maxlength=”500″></td>
</tr>
</table>
<div align=”center”><input type=”submit” name=”submit” value=”修改密码”></div>
</table>
</form>
</div>
<?php
}
?>

上面的代码有两个方法:1是生成验证码,2是通过验证码修改密码.
我们先看看验证代码是如何生成的:
$emailrand=$bbs_forgotpassword->forgotpass($_POST[“email”]);我们把值传递给forgotpass函数
其原型是:

private $email;
private $randid;
function forgotpass($email) //在这接收了用户的邮件,
{
$this->email=$email; //邮件赋值
$sql=”select * from admin where mail=’$this->email’ and yesno=’1′”;
//找回密码的时候,必须验证用户是否是为通过审核的.
$rs=mysql_query($sql);
if(mysql_num_rows($rs)!=0)
{//如果存在找回的邮箱并且是通过审核的,
//开始创建随机数
$temprandid=md5(rand(1,1000000)); //随机数=md5过后的1~1000000
//在这特别说下,使用MD5之后的随机数,就算别人想暴力破解,也需要很大的难度,1-1000000的MD5码前6位,挺复杂的.
$this->randid=substr($temprandid,0,6); //提取MD加密后的字符串的前6位赋值给$randid
#这里增加一个方法,判断找回密码邮件里是否存在当前要找回密码的邮箱字段,有则提示重复.
$sql1=”SELECT * FROM forgotpassword where email=’$this->email'”;
$rs1=mysql_query($sql1);
if(mysql_num_rows($rs1)!=0)
{//如果找回密码里的确存在,那么判断时间的大小,超过30分钟的话删除旧的,并且重新生成.
$time=date(“Y-m-d H:i:s”);
$tempemail=mysql_query($sql1); //提取当前找回邮件的时间
while($row=mysql_fetch_object($tempemail))
{
$t=$row->time; //获得验证码生成时间.
}
$o=strtotime($time)-strtotime($t);
//strtotime()函数将任何英文文本的日期时间描述解析为 Unix 时间戳
if($o>1800) //如果SQL找回密码里的当前用户时间大于半小时,自动清除并跳出.
{
$delsql=”delete from forgotpassword where email=’$this->email'”;
mysql_query($delsql); //删除当前密码找回记录并跳出,执行后面的重新创建
}
else
{
//时间还没超过1800秒,重复提交禁止通过
echo “<script language=\”JavaScript\”>alert(\”错误::\\n重复找回\\n\”);</script>”;
echo “<script>setTimeout(\”this.location=’index.php’\”,0);</script>”;
exit;
}
}
$sql1 = mysql_query(“select max(id) sqlmaxid from forgotpassword”);
while($sqlmaxid = mysql_fetch_object($sql1)) //读取最大userid值得
$tempmaxid = $sqlmaxid->sqlmaxid; //提取最大id
$insqlmaxid=$tempmaxid+1; //最大id+1
$time=date(“Y-m-d H:i:s”);$ip=$_SERVER[“REMOTE_ADDR”];
mysql_query(“INSERT INTO forgotpassword(id,email,randid,time,ip)
VALUES(‘$insqlmaxid’,’$this->email’,’$this->randid’,’$time’,’$ip’)”);
return $this->sendmailto($this->email,$this->randid);//返回收信人和随机数(邮件内容)给sendmailto函数
}
else
{
//否则输出该邮箱不存在
echo “<script language=\”JavaScript\”>alert(\”邮箱不存在\”);</script>”;
echo “<script>setTimeout(\”this.location=’index.php’\”,0);</script>”;exit;
}
}

到这里,如果用户找回密码申请成功,SQL里就有了验证码,申请的邮箱等记录了
接下来要做的,就是要把验证码发送到申请的邮箱
所以有上面的代码有这么一句:
return $this->sendmailto($this->email,$this->randid); //把申请邮箱和验证码返回给sendmailto函数
我们看看该函数:

function sendmailto($mailto,$mailbody) //接受教育收件人和验证码
{
$sql=”SELECT *FROM adminforgotpassword”;
$tempsql=mysql_query($sql); //sql语句
while($row=mysql_fetch_object($tempsql)) //提出后端设置的SMTP服务器参数
{
$smtpserver=$row->smtpserver; //SMTP服务器
$smtpserverport=$row->smtpserverport; //SMTP服务器端口
$smtpusermail=$row->smtpusermail; //SMTP服务器的用户邮箱
$smtpuser=$row->smtpuser; //SMTP服务器的用户帐号
$smtppass=$row->smtppass; //SMTP服务器的用户密码
}
$mailsubject=”修改密码验证码”; //邮件主题
$this->smtpemailto=$mailto; //收件人
$this->mailbody=”请在网站找回密码处输入该验证码:”.$mailbody; //邮件内容,在这里加上了验证代码
$mailsubject=”=?UTF-8?B?” . base64_encode($mailsubject) . “?=”; //防止乱码
$mailtype=”HTML”; //邮件格式为HTML.建议不用TXT,部分邮箱不支持.
echo “<script language=\”JavaScript\”>alert(\”验证码已发送\\n请在30分内修改密码\\n\”);</script>”;
require_once (“sendmail.php”);
//提示发送成功,本来这个要放在SENDMAIL文件里的,但由于SMTP是别人写的,作者只保证能正常调用就是
//不再进行他人的SMTP类进行修改
$smtp = new smtp($smtpserver, $smtpserverport, true, $smtpuser, $smtppass);
//这里面的一个true是表示使用身份验证,否则不使用身份验证.
$smtp->debug= true; //是否显示发送的调试信息
$smtp->sendmail($this->smtpemailto, $smtpusermail, $mailsubject, $this->mailbody, $mailtype);
//把参数返回给sendmail函数处理.
}

前面说了:
//首先肯定是要判断有无$_POST的数据,如果存在这3个参数,表示用户是在修改新密码,(已获取验证代码)
回看这一句:
$bbs_system->email_password($_POST[“email”],$_POST[“randid”],$_POST[“newpassword”]);
用户输入邮箱,验证码,新密码的时候,提交给email_password函数处理

private $email_password_mail;
private $email_password_randid;
private $email_password_newpassword;
//作者定义了三个私有的数据成员来接收参数
function email_password($mail,$randid,$newpassword)
{
$this->email_password_mail=$mail;
$this->email_password_randid=$randid;
$this->email_password_newpassword=$newpassword;
$sql=”select * from forgotpassword where email=’$this->email_password_mail'”;
//首先判断输入的EMAIL在找回密码字段是否存在
$rs=mysql_query($sql);
if(mysql_num_rows($rs)!=0) //如果存在表示的确有收到用户申请找回密码的申请
{
$time=date(“Y-m-d H:i:s”); //获得当前时间
$tempemail=mysql_query($sql); //再一次执行SQL,不过现在是要提取出数据
while($row=mysql_fetch_object($tempemail))
{
$e=$row->email;$i=$row->randid;$t=$row->time; //获得邮件用户,验证码,时间.
}
$o=strtotime($time)-strtotime($t); //判断找回的时间差
//strtotime为计算时间,具体GOOGLE
if($o>1800) //由于时间是以秒计算,判断是否超时
{
//如果时间超过30分钟,达到找回密码的最大时间,删除该条找回密码申请
$delsql=”delete from forgotpassword where email=’$this->email_password_mail'”;
mysql_query($delsql); //删除当前密码找回记录
echo “<script language=\”JavaScript\”>alert(\”超过时间限制\”);</script>”;
echo “<script>setTimeout(\”this.location=’index.php’\”,0);</script>”;
exit; //退出脚本
}
if($i!=$this->email_password_randid) //判断验证码是否正确.
{ //如果还在时间内,判断用户输入的验证码和数据库里的是否不相同
echo “<script language=\”JavaScript\”>alert(\”验证码出错\”);</script>”;
echo “<script>setTimeout(\”this.location=’index.php’\”,0);</script>”;
exit; //退出
}
//如果时间在范围内,验证码为真
$newpassword=md5($this->email_password_newpassword);//将用户输入的新密码进行MD5加密
$sql=”UPDATE admin SET password=’$newpassword’ WHERE mail=’$this->email_password_mail'”;
//指定用户的邮箱更新用户的密码SQL
mysql_query($sql);//执行修改当前邮箱的用户的密码,切记要使用MD5
$delsql=”delete from forgotpassword where email=’$this->email_password_mail'”;
//同时删除该用户申请找回密码的记录
mysql_query($delsql);
echo “<script language=\”JavaScript\”>alert(\”密码修改成功\”);</script>”;
echo “<script>setTimeout(\”this.location=’index.php’\”,0);</script>”;

}
else
{
echo “<script language=\”JavaScript\”>alert(\”您输入错误或者不存在\”);</script>”;
echo “<script>setTimeout(\”this.location=’index.php’\”,0);</script>”;exit;
}
}

很多SQL语句作者没用IF来判断是否会出错,如果是自学的问题多了,可以先用IF判断MYSQL_QUERY()是否正常执行
作者自学就是这么起来的,当更了解PHP+MYSQL之后,基本只需要查看传递的参数和语句命令就可以了.

好了,到此,一个简单的邮件找回就可以了.

关于作者

清心醉 administrator

发表评论

请输入验证码: