原理很简单:
用户找回密码的时候,填写用户名,程序得到用户名便可以去数据库取出用户对应的密码以及当时填写的邮箱,
根据用户名和密码生成一个key=md5(username+password),然后$string=base64_encode(username+key),发送邮件给用户,邮件内容为http://www.xxx.com?p=$string,
用户点击链接地址,程序进行相关操作,先$str=base64_decode($string),之后$arr=explode('+',$str),$arr[0]肯定为用户名,根据用户名得到用户的密码,再使用key=md5(username+password),判断$arr[1]与key是否一致,一致的话就输出两个表单,让用户填写新的密码和确认密码。
问题一:
会不会最后一步的输入新的密码的是,用户把username改成别人的,然后再提交新的密码过去?
问题二:
为什么不直接在发送给用户的邮箱里面地址这样写http://www.xxx.com?username=xxx&key=$string ?
答: 原理其实是一致的
扩展:
一:如何让这个找回密码的链接具有时效性(比如15分钟后失效)?
答:原理:在地址栏上面加上一个时间和这个时间的加密,如果用户点击这个链接去处理的当时时间-地址栏的时间大于15分钟,则这个找回密码的链接失效
http://www.xxx.com?username=xxx&key=$string &code=md5("自己定义的常量串".$time)&time=$time
其中code是用来检验time是否有修改过。
第二种:
发送邮件找回密码功能(分析加实例)(如有错误请指出,谢谢)
分析:
大致思路就是发送邮件→连接邮件里的URL→修改密码
1.为了保证安全性,需要生成发送到邮件的URL,主要参数(用户名,过期时间,key(key 需要在每次运行是自动生成随机码), IP等等) 然后将URL发送到邮箱。
2.保存发送的参数(建议保存在数据库)
3.解析url:首先根据用户名从数据库中查找出密钥key和过期时间,没有则表示该请求 是伪造的或者过期的,然后验证签名,验证过期时间,都验证通过,就可以修改密码, 密码修改完以后,删除数据库中的记录。
实例代码:
分为发送邮箱页面和修改密码页面:
一.发送邮箱页面
string strUserName = txtUserName.Value.Trim();
string strEail = txtEmail.Value.Trim();
//生成随机密码
string rand = "";
Random ramPwd = new Random();
string pwd = ramPwd.Next(100000, 9999999).ToString();
rand = pwd;
string key = rand + strName + email + "Base";
if (!string.IsNullOrEmpty(strUserName) && !string.IsNullOrEmpty(strEail))
{
//发送邮件
StringBuilder sb = new StringBuilder();
sb.Append("亲爱的" + strUserName + "您好:<br/><br/>");
sb.Append("点击以下链接设置新密码。<br/><br/>");
sb.Append("<a href =\"http://www.xxxx.com/findpwd.aspx?key=" + key + "&time=" + time + "\">http://www.xxxx.com/findpwd.aspx?key=" + key + "&time=" + time + " </a><br/><br/>");
sb.Append("(如果无法点击该URL链接地址,请将它复制并粘帖到浏览器的地址输入框,然后单击回车即可。)<br/><br/>");
sb.Append("注意:请您在收到邮件24小时内使用,否则该链接将会失效。<br/><br/>");
sb.Append("我们将一如既往、热忱的为您服务!<br/><br/>");
string MessageBody = sb.ToString();
Sends(strEail, "no_reply@xxxx.com", "xxxx--找回密码", MessageBody, "123456");
//向find_password_log表添加数据
AddFindPassword(strUserName, strEail,key);
Response.Write("<script>alert('邮件已发送到你的邮箱,请注意查收!');location.href='/';</script>");
}
}
//向表find_password_log中添加数据
private void AddFindPassword(string strName, string email, string key)
{
//向find_password_log表中插入随机生成的密码(MD5加密) ,时间,IP
SummerBase.BLL.find_password_log bllFind = new SummerBase.BLL.find_password_log();
SummerBase.Model.find_password_log modelFind = new SummerBase.Model.find_password_log();
if (modelFind != null)
{
modelFind.Md5 = MFunction.Md5New(key).ToString();
modelFind.CreateTime = SummerBase.Utils.Util.TimeToUnixTimes(DateTime.Now.ToString());
modelFind.IP = Page.Request.UserHostAddress;
time = modelFind.CreateTime;
key = modelFind.Md5;
}
bllFind.Add(modelFind);
}
//发送邮件代码
public static void Sends(string email, string formto, string content, string body, string upass)
{
string name = "no_reply@xxxx.com";
string smtp = "smtp.exmail.sina.com";
SmtpClient _smtpClient = new SmtpClient();
_smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;//指定电子邮件发送方式
_smtpClient.Host = smtp; //指定SMTP服务器
_smtpClient.Credentials = new System.Net.NetworkCredential(name, upass);//用户名和密码
MailMessage _mailMessage = new MailMessage();
//发件人,发件人名
_mailMessage.From = new MailAddress(formto, "xxxx公司");
//收件人
_mailMessage.To.Add(email);
_mailMessage.SubjectEncoding = System.Text.Encoding.GetEncoding("gb2312");
_mailMessage.Subject = content;//主题
_mailMessage.Body = body;//内容
_mailMessage.BodyEncoding = System.Text.Encoding.GetEncoding("gb2312");//正文编码
_mailMessage.IsBodyHtml = true;//设置为HTML格式
_mailMessage.Priority = MailPriority.High;//优先级
try
{
_smtpClient.Send(_mailMessage);
}
catch (Exception)
{
}
}
二,修改密码页。
这个很简单咯,代码就没贴出来
1根据接受的参数和数据中添加的参数进行比较,如果验证通过,就修改密码,如果验证失败则给出提示,重新发送邮件。