找回密码

Posted zhengwei_cq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了找回密码相关的知识,希望对你有一定的参考价值。

登陆功能中有一项是当用户忘记密码后需要找回密码

1、当用户点忘记密码后我们呈现的是一个表单,要求用户输入用户名和邮箱号,输完信息后点击发送邮件,发邮件的代码如下:

public string SendMail(string userid, string email)
        {
            if(string.IsNullOrEmpty(userid))
                return "请输入用户登录名!";
            if (string.IsNullOrEmpty(email))
                return "请输入邮箱地址!";
            MembershipUser user = Membership.GetUser(userid, false);
            if (user == null)
            {
                return string.Format("找不到用户:{0}!", userid);
            }
            ProfileBase profile = ProfileBase.Create(userid);
            if (profile.GetPropertyValue("EmailAddresses") != null)
            {
                bool IsApprovaled = user.IsApproved;
                bool IsLocked = user.IsLockedOut;

                if (!IsApprovaled)
                {
                    return string.Format("用户:{0}已被禁用,无法登录,请联系管理员!", userid);
                }
                if (IsLocked)
                {
                    return string.Format("用户:{0}已被锁定,无法登录,请联系管理员!", userid);

                }
                string myemail = profile.GetPropertyValue("EmailAddresses").ToString();
                if (myemail.ToUpper().Trim() != email.ToUpper().Trim())
                {
                    return string.Format("用户:{0}对应的邮箱:{1}不存在,请重新输入邮箱!", userid, email);
                }
                else
                {
                    string unitname = string.Empty;
                    try
                    {
                        string unitcode = profile.GetPropertyValue("UnitCode").ToString();
                        unitname = UnitService.GetUnitByCode(unitcode).Name;
                    }
                    catch (Exception ep)
                    {
                    }
                    string username = profile.GetPropertyValue("Name").ToString();
                    string userinfo = string.Format("{0}您好!<br/>姓名:{1}<br/>单位:{2}<br/>", user.UserName, username, unitname);
                    string paramuid = DESHelper.Encrypt(string.Format("{0}|{1}", user.UserName, DateTime.Now), "findpassword");
                    string callbackUrl =string.Format("admin/resetpassword.aspx?userid={0}",paramuid);
                    string content = userinfo + "请通过单击 <a href=\"" + ConfigHelper.CurrentConfig.FindpasswordUrl + callbackUrl + "\">此处</a>来重置你的密码";
                    new MailService().SendMail(email, "中石油出国系统系统:找回密码", content, null, null,true);
                    return "";
                }
            }
            else
            {
                return string.Format("用户:{0}邮箱不存在,请重新输入邮箱!", userid);
            }
        }

注:new MailService().SendMail(email, "中石油出国系统系统:找回密码", content, null, null,true);这个方法是我项目中已有的发送邮件的方法。DESHelper也是我项目中封装好的类,在后面会全部给出

2、邮件发送后用户需要进入邮箱点击进行验证,点击后访问系统中 resetpassword.aspx 页面,该页面有一个密码重置按钮,我们来看看这个页面的后台代码

protected void Page_Load(object sender, EventArgs e)
        {

            string userid = GetStringPara("userid", "");
            string encodeuserid = DESHelper.Decrypt(userid, "findpassword");
            string[] stringuid = encodeuserid.Split(|);
            string userId = stringuid[0];
            DateTime logtime = DateTime.Parse(stringuid[1]);
            if (logtime >= DateTime.Now.AddMinutes(-30))
            {
                lbUserId.Text = userId;
            }
            else
                Response.Redirect("FindPassword.aspx");
        }

注:在这个页面的后台我们将用户的数据进行解密,存入到一个服务端控件中去

3、点击重置密码后用户的密码被重置成了默认的值、看下面的方法

protected void btReset_Click(object sender, EventArgs e)
        {
            string userid = lbUserId.Text;
            MembershipUser user = Membership.GetUser(userid, false);
            if (user == null)
            {
                ShowInfo(string.Format("用户:{0}不存在,无法重置密码,请联系管理员!", userid));
                return;
            }
            bool IsApprovaled = user.IsApproved;
            bool IsLocked = user.IsLockedOut;

            if (!IsApprovaled)
            {
                ShowInfo(string.Format("用户:{0}已被禁用,无法登录,请联系管理员!", userid));
                return;
            }
            if (IsLocked)
            {
                ShowInfo(string.Format("用户:{0}已被锁定,无法登录,请联系管理员!", userid));
                return;
            }
            string newPassword = user.ResetPassword();
            user.ChangePassword(newPassword, tbPassword.Text);

            Response.Write(string.Format("<script language=‘javascript‘>alert(‘重置密码成功,请重新登录!‘);window.location=‘{0}‘;</script>",ConfigHelper.CurrentConfig.ShowNewsUrl));
        }

注:项目中用的 Membership 框架,重置和改变密码都是用了框架中的方法

至此密码重置完成了,最后贴上我们项目中已有的类的方法:

 MailService类

public class MailService
    {
        public static MailMessage mailMessage = new MailMessage();
        public static string AttachmentPath;
        public List<Attachment> attchments;

        /// <summary>
        /// 发送邮件的方法
        /// </summary>
        /// <param name="toMail">目的邮件地址</param>
        /// <param name="title">发送邮件的标题</param>
        /// <param name="content">发送邮件的内容</param>
        /// <param name="CopytoMail">抄送邮件地址</param>
        /// <param name="FilePath">附件路径,附件之间以"|"相间隔</param>
        public void SendMail(string toMail, string title, string content, string CopyMail, string FilePath, bool isBodyhtml)
        {
            try
            {
                mailMessage.To.Clear();
                mailMessage.CC.Clear();
                mailMessage.AlternateViews.Clear();
                mailMessage.Headers.Clear();
                Encoding chtEnc = Encoding.BigEndianUnicode;//Encoding.UTF8
                AttachmentPath = FilePath;

                AddMailTo(toMail, chtEnc);

                AddCopyTo(CopyMail, chtEnc);

                //邮件标题编码
                mailMessage.SubjectEncoding = chtEnc;
                //邮件主题
                mailMessage.Subject = string.IsNullOrEmpty(title) ? "No Subject".ToString() : title.ToString();
                mailMessage.SubjectEncoding = System.Text.Encoding.UTF8;
                //邮件内容
                mailMessage.Body = string.IsNullOrEmpty(content) ? "No Content".ToString() : content.ToString();
                //邮件内容编码
                mailMessage.BodyEncoding = System.Text.Encoding.UTF8;
                mailMessage.IsBodyHtml = isBodyHtml;//是否允许内容为 HTML 格式
                
                AddAttach(FilePath);//添加多个附件            

                //如果发送失败,SMTP 服务器将发送失败邮件告诉我
                mailMessage.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;

                //发送邮件的优先等级(有效值为High,Low,Normal)
                mailMessage.Priority = MailPriority.Normal;
                mailMessage.DeliveryNotificationOptions = DeliveryNotificationOptions.OnSuccess;

                SmtpClient client = new SmtpClient();
                client.Timeout = 120000;
                //异步发送完成时的处理事件
                client.SendCompleted += new SendCompletedEventHandler(client_SendCompleted);
                //发送邮件
                client.Send(mailMessage); //同步发送
                //client.SendAsync(mailMessage, mailMessage.To); //异步发送 (异步发送时页面上要加上Async="true" )
            }
            catch (Exception ep)
            {  
                throw new ApplicationException(string.Format("发送邮件失败:\r\n {0}",ep.Message));
            }
        }

        /// <summary>
        /// 增加抄送人(支持多个)
        /// </summary>
        /// <param name="CopyMail">抄送人地址列表</param>
        /// <param name="chtEnc">编码</param>
        private void AddCopyTo(string CopyMail, Encoding chtEnc)
        {
            if (!string.IsNullOrEmpty(CopyMail))
            {
                string strCopyMail = CopyMail.Replace("", ";");
                if (strCopyMail.Contains(";"))
                {
                    string[] mails = strCopyMail.Split(;);
                    foreach (string mail in mails)
                    {
                        if (!string.IsNullOrEmpty(mail))
                            mailMessage.CC.Add(new MailAddress(mail, mail.ToString(), chtEnc));
                    }
                }
                else
                {
                    mailMessage.CC.Add(new MailAddress(CopyMail, CopyMail.ToString(), chtEnc));
                }
            }

        }

         //<summary>
         //增加收件人(支持多个)
         //</summary>
         //<param name="toMail">收件人地址列表</param>
         //<param name="chtEnc">编码</param>
        private void AddMailTo(string toMail, Encoding chtEnc)
        {
            string strToMail = toMail.Replace("", ";");
            if (strToMail.Contains(";"))
            {
                string[] mails = strToMail.Split(;);
                foreach (string mail in mails)
                {
                    if (!string .IsNullOrEmpty(mail))
                        mailMessage.To.Add(new MailAddress(mail, mail.ToString(), chtEnc));
                }
            }
            else
            {
                mailMessage.To.Add(new MailAddress(toMail, toMail.ToString(), chtEnc));        
            }
        }


        /// <summary>
        /// 添加附件
        /// </summary>
        /// <param name="FilePath">文件路径</param>
        private void AddAttach(string FilePath)
        {
            attchments = GetAttachByPath(FilePath);
            if (attchments.Count > 0)
            {
                if (mailMessage.Attachments.Count > 0)
                    mailMessage.Attachments.Clear();
                foreach (Attachment item in attchments)
                {
                    mailMessage.Attachments.Add(item);
                }
            }
        }

        /// <summary>
        /// 根据文件路径获得要添加的附件文件列表
        /// </summary>
        /// <param name="FilePath">文件路径</param>
        /// <returns>附件文件列表</returns>
        private List<Attachment> GetAttachByPath(string FilePath)
        {
            List<Attachment> attachs = new List<Attachment>();
            //校验
            if (string.IsNullOrEmpty(FilePath)) { return new List<Attachment>(); }
            if (!FilePath.Contains("|")) { return new List<Attachment>(); }

            //去掉路径最后一位的"|"
            List<string> paths = GetPaths(ref FilePath);
            foreach (string path in paths)
            {
                attachs.Add(new Attachment(path, MediaTypeNames.Application.Octet));
            }
            return attachs;
        }

        /// <summary>
        /// 获得附件文件路径列表
        /// </summary>
        /// <param name="FilePath"></param>
        /// <returns></returns>
        private static List<string> GetPaths(ref string FilePath)
        {
            FilePath = FilePath.Remove(FilePath.Length - 1);
            string[] filepaths = FilePath.Split(|);
            List<string> paths=new List<string>();
            foreach (string path in filepaths)
            {
                paths.Add(path);
            }
            return paths;
        }

        //发送完毕后的事件
        void client_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                System.Web.HttpContext.Current.Response.Write("发送的邮件已被取消!");
            }
            if (e.Error == null)
            {
                System.Web.HttpContext.Current.Response.Write("邮件已成功发送!");
                ////释放资源
                //mailMessage.Dispose();
                mailMessage.Attachments.Clear(); //邮件发送完毕,释放对附件的锁定(这种方式会有问题,如果第二次发同一个文件,会报异常)
                DisposeAttchment();//邮件发送完毕,释放对附件的锁定
                //DeleteAttachFile();                
            }
            else
            {
                System.Web.HttpContext.Current.Response.Write(e.Error.Message + " 原因是:" + e.Error.InnerException);
            }
        }



        /// <summary>
        /// 删除附件的源文件
        /// </summary>
        private static void DeleteAttachFile()
        {
            List<string> paths = GetPaths(ref AttachmentPath);
            foreach (string path in paths)
            {
                if (System.IO.File.Exists(path))
                {
                    System.IO.File.Delete(path);
                }
            }
        }

        /// <summary>
        /// 邮件发送完毕,释放对附件的锁定
        /// </summary>
        private void DisposeAttchment()
        {
            if(attchments.Count>0)
            {
                foreach (Attachment attach in attchments)
                {
                    attach.Dispose();
                }
            }
            
        }

    }

DESHelper类

 /// <summary>
    /// DES对称加密
    /// </summary>
    public static class DESHelper
    {
        /// <summary>
        /// 根据用户名解密
        /// </summary>
        /// <param name="val"></param>
        /// <param name="userid"></param>
        /// <returns></returns>
        public static string Decrypt(string val, string userid = "")
        {

            var key = GetKey(userid);
            var iv = GetDefaultIV();
            return Decrypt(val, key, iv);
        }

        /// <summary>
        /// 根据用户名加密
        /// </summary>
        /// <param name="val"></param>
        /// <param name="userid"></param>
        /// <returns></returns>
        public static string Encrypt(string val, string userid = "")
        {

            var key = GetKey(userid);
            var iv = GetDefaultIV();
            return Encrypt(val, key, iv);
        }

        /// <summary>
        /// Des加密方法
        /// </summary>
        /// <param name="val"></param>
        /// <param name="key"></param>
        /// <param name="IV"></param>
        /// <returns></returns>
        public static string Encrypt(string val, string key, string IV, CipherMode cipherMode = CipherMode.ECB)
        {
            try
            {
                if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(key))
                {
                    throw new Exception("密钥和偏移向量不足8位");
                }

                if (key.Length > 8) key = key.Substring(0, 8);
                if (IV.Length > 8) IV = IV.Substring(0, 8);

                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                byte[] btKey = Encoding.Default.GetBytes(key);
                byte[] btIV = Encoding.Default.GetBytes(IV);
                StringBuilder builder = new StringBuilder();
                using (MemoryStream ms = new MemoryStream())
                {
                    byte[] inData = Encoding.Default.GetBytes(val);
                    using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(btKey, btIV), CryptoStreamMode.Write))
                    {
                        cs.Write(inData, 0, inData.Length);
                        cs.FlushFinalBlock();
                    }

                    foreach (byte num in ms.ToArray())
                    {
                        builder.AppendFormat("{0:X2}", num);
                    }
                } 
                return builder.ToString();
            }
            catch // (Exception ex)
            {
                return "";
            }
        }

        /// <summary>
        /// Des解密方法
        /// cbc模式:(key值和iv值一致)
        /// </summary>
        /// <param name="val"></param>
        /// <param name="key"></param>
        /// <param name="IV"></param>
        /// <returns></returns>
        public static string Decrypt(string val, string key, string IV, CipherMode cipherMode = CipherMode.ECB)
        {
            try
            {
                if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(key))
                {
                    throw new Exception("密钥和偏移向量不足8位");
                }

                if (key.Length > 8) key = key.Substring(0, 8);
                if (IV.Length > 8) IV = IV.Substring(0, 8);

                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                byte[] btKey = Encoding.Default.GetBytes(key);
                byte[] btIV = Encoding.Default.GetBytes(IV);
                using (MemoryStream ms = new MemoryStream())
                {
                    byte[] inData = new byte[val.Length / 2];
                    for (int i = 0; i < (val.Length / 2); i++)
                    {
                        int num2 = Convert.ToInt32(val.Substring(i * 2, 2), 0x10);
                        inData[i] = (byte)num2;
                    }

                    using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(btKey, btIV), CryptoStreamMode.Write))
                    {
                        cs.Write(inData, 0, inData.Length);
                        cs.FlushFinalBlock();
                    }

                    return Encoding.Default.GetString(ms.ToArray());
                }
            }
            catch // (System.Exception ex)
            {
                return "";
            }
        }

        /// <summary>
        /// Md5加密
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string MD5(string str)
        {
            if (string.IsNullOrEmpty(str)) return str;
            System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();
            string encoded = BitConverter.ToString(md5.ComputeHash(Encoding.UTF8.GetBytes(str))).Replace("-", "");
            return encoded;
        }

        private static string GetKey(string key)
        {
            string defaultKey = "C560F02F693B4A0BA62D2B3B5FB74534";
            string sTemp = defaultKey;
            if (!string.IsNullOrEmpty(key))
            {
                sTemp = string.Concat(key, defaultKey.Substring(key.Length, 32 - key.Length));
            }
            return MD5(sTemp).Substring(0, 8);
        }
        /// <summary>   
        /// 获得初始向量IV 
        /// </summary>   
        /// <returns>初试向量IV</returns>   
        private static string GetDefaultIV()
        {
            string sTemp = "87DE696F56DE49C0B96EB85139A48805";
            return MD5(sTemp).Substring(0, 8);
        }
    }

 

以上是关于找回密码的主要内容,如果未能解决你的问题,请参考以下文章

邮箱验证修改密码,通过邮箱找回密码

通过游戏学python 3.6 第一季 第九章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁定账

通过游戏学python 3.6 第一季 第七章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码--优化代码及注释--简单账号密码登陆--账号的注册查询和密码的找回修改--锁定账

强制找回GitLab管理员账户密码的方法

zabbix 忘记密码,找回密码

找回密码实际项目