个人觉得,邮箱激活这种做法,最重要功能,是为了验证邮箱的邮箱的有效性,其次防止机器人机械注册无良账号。
点击“下一步”,发送邮件。把用户提交的表单信息放到XML,等他激活了之后再添加到数据库,然后把XML的相关信息删掉。当然,最好的做法是在直接在数据库里面设置一个状态字段,我们只需要修改一下这两个值就可以了。个人觉得,两个的存储量是一样的,但是操作的话,XML还是麻烦一点,所以推荐使用数据设计状态这种做法。
在发送的邮件里,有激活的链接,比如:http://localhost:2556/WebSite/Register.aspx?Re=YeXJAEYeOXJiJOYeeUQinYeAEJAEHjJHjEs*wenjunli2
这个地址是经过加密的。“*”之前的时间(精确到毫秒),为什么要做这个时间呢,是为了设定在多少时间后失效,失效后把存储的数据删掉(激活失效这个功能)。“*”之后是用户名,其实也应该经过加密,上面没有加密。真正实现激活的是靠这个用户名,如果数据库中存在这个用户名,并且时间没有过期,则激活成功,把数据库用户状态修改。
public class MyService { // 对称加密算法提供器 private ICryptoTransform encryptor; // 加密器对象 private ICryptoTransform decryptor; // 解密器对象 private const int BufferSize = 1024; public MyService(string algorithmName, string key) { SymmetricAlgorithm provider = SymmetricAlgorithm.Create(algorithmName); provider.Key = Encoding.UTF8.GetBytes(key); provider.IV = new byte[] { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; encryptor = provider.CreateEncryptor(); decryptor = provider.CreateDecryptor(); } public MyService(string key) : this("TripleDES", key) { } // 加密算法 private string Encrypt(string clearText) { // 创建明文流 byte[] clearBuffer = Encoding.UTF8.GetBytes(clearText); MemoryStream clearStream = new MemoryStream(clearBuffer); // 创建空的密文流 MemoryStream encryptedStream = new MemoryStream(); CryptoStream cryptoStream = new CryptoStream(encryptedStream, encryptor, CryptoStreamMode.Write); // 将明文流写入到buffer中 // 将buffer中的数据写入到cryptoStream中 int bytesRead = 0; byte[] buffer = new byte[BufferSize]; do { bytesRead = clearStream.Read(buffer, 0, BufferSize); cryptoStream.Write(buffer, 0, bytesRead); } while (bytesRead > 0); cryptoStream.FlushFinalBlock(); // 获取加密后的文本 buffer = encryptedStream.ToArray(); string encryptedText = Convert.ToBase64String(buffer); return encryptedText; } // 解密算法 private string Decrypt(string encryptedText) { byte[] encryptedBuffer = Convert.FromBase64String(encryptedText); Stream encryptedStream = new MemoryStream(encryptedBuffer); MemoryStream clearStream = new MemoryStream(); CryptoStream cryptoStream = new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read); int bytesRead = 0; byte[] buffer = new byte[BufferSize]; do { bytesRead = cryptoStream.Read(buffer, 0, BufferSize); clearStream.Write(buffer, 0, bytesRead); } while (bytesRead > 0); buffer = clearStream.GetBuffer(); string clearText = Encoding.UTF8.GetString(buffer, 0, (int)clearStream.Length); return clearText; } /// <summary> ///加密 /// </summary> /// <param name="clearText"></param> /// <param name="key"></param> /// <returns></returns> public static string Encrypt(string clearText, string key) { MyService helper = new MyService(key); return helper.Encrypt(clearText); } /// <summary> /// 解密 /// </summary> /// <param name="encryptedText"></param> /// <param name="key"></param> /// <returns></returns> public static string Decrypt(string encryptedText, string key) { MyService helper = new MyService(key); return helper.Decrypt(encryptedText); } } 上面第一个是自己写的一个时间加密规则,第二个是.net的加密规则,其实也可以用MD5,不过我不懂用,也没用过。 /// <summary> /// 发送邮件(注册) /// </summary> /// <param name="name">用户姓名</param> /// <param name="userName">用户名</param> /// <param name="userPass">密码</param> /// <param name="EmailAdd">邮箱地址</param> /// <returns></returns> public static bool sendEmail(string name, string userName, string userPass, string EmailAdd) { try { SmtpClient smtp = new SmtpClient(); //实例化一个SmtpClient smtp.DeliveryMethod = SmtpDeliveryMethod.Network; //将smtp的出站方式设为 Network smtp.EnableSsl = false;//smtp服务器是否启用SSL加密 smtp.Host = "smtp.sina.com.cn"; //指定 smtp 服务器地址 smtp.Port = 25; //指定 smtp 服务器的端口,默认是25,如果采用默认端口,可省去 //如果你的SMTP服务器不需要身份认证,则使用下面的方式,不过,目前基本没有不需要认证的了 smtp.UseDefaultCredentials = true; //如果需要认证,则用下面的方式 smtp.Credentials = new NetworkCredential("qinlin1991@sina.com", "3155446"); MailMessage mm = new MailMessage(); //实例化一个邮件类 mm.Priority = MailPriority.High; //邮件的优先级,分为 Low, Normal, High,通常用 Normal即可 mm.From = new MailAddress("shirilimu@sina.com", "求知科技", Encoding.GetEncoding(936)); //收件方看到的邮件来源; //第一个参数是发信人邮件地址 //第二参数是发信人显示的名称 //第三个参数是 第二个参数所使用的编码,如果指定不正确,则对方收到后显示乱码 //936是简体中文的codepage值 //注:上面的邮件来源,一定要和你登录邮箱的帐号一致,否则会认证失败 mm.ReplyTo = new MailAddress("shirilimu@sina.com", "求知科技", Encoding.GetEncoding(936)); //ReplyTo 表示对方回复邮件时默认的接收地址,即:你用一个邮箱发信,但却用另一个来收信 //上面后两个参数的意义, 同 From 的意义 //mm.CC.Add("a@163.com,b@163.com,c@163.com"); //邮件的抄送者,支持群发,多个邮件地址之间用 半角逗号分开 //当然也可以用全地址,如下: //mm.CC.Add(new MailAddress(EmailAdd, "覃林", Encoding.GetEncoding(936))); //mm.CC.Add(new MailAddress("b@163.com", "抄送者B", Encoding.GetEncoding(936))); //mm.CC.Add(new MailAddress("c@163.com", "抄送者C", Encoding.GetEncoding(936))); //mm.Bcc.Add("d@163.com,e@163.com"); //邮件的密送者,支持群发,多个邮件地址之间用半角逗号 分开 //当然也可以用全地址,如下: //mm.CC.Add(new MailAddress("d@163.com", "密送者D", Encoding.GetEncoding(936))); //mm.CC.Add(new MailAddress("e@163.com", "密送者E", Encoding.GetEncoding(936))); //mm.Sender = new MailAddress("xxx@xxx.com", "邮件发送者", Encoding.GetEncoding(936)); //可以任意设置,此信息包含在邮件头中,但并不会验证有效性,也不会显示给收件人 //说实话,我不知道有啥实际作用,大家可不理会,也可不写此项 //mm.To.Add("g@163.com,h@163.com"); //邮件的接收者,支持群发,多个地址之间用半角逗号 分开 //当然也可以用全地址添加 mm.To.Add(new MailAddress(EmailAdd, name, Encoding.GetEncoding(936))); //mm.To.Add(new MailAddress("h@163.com", "接收者h", Encoding.GetEncoding(936))); mm.Subject = "考无忧-个人账号信息"; //邮件标题 mm.SubjectEncoding = Encoding.GetEncoding(936); // 这里非常重要,如果你的邮件标题包含中文,这里一定要指定,否则对方收到的极有可能是乱码。 // 936是简体中文的pagecode,如果是英文标题,这句可以忽略不用 mm.IsBodyHtml = true; //邮件正文是否是HTML格式 mm.BodyEncoding = Encoding.GetEncoding(936); //邮件正文的编码, 设置不正确, 接收者会收到乱码 mm.Body = "<table style='border:3px solid #D9F4FF;658px;' cellspacing='0' cellpadding='0'><tr><td class='style1'><table style='border:1px solid #65C3D6;font-size:12px;' cellspacing='0' cellpadding='0'><tr><td style='657px;'><img src='http://www.k51.com.cn/images/logo.jpg' /><br/><b style=' color:#F3750F'>" + name + "</b>:" + "<table cellspacing='0' cellpadding='5' border='0' style=' 653px; margin-bottom: 0px; margin-top:-10px'><tr><td style='padding:20px 16px;color:#333;'><table cellspacing='0' cellpadding='0' border='0'><tr><td style='padding-left:14px;' class='style3'>您好,感谢您注册考无忧!祝你使用愉快,才识倍增!</td></tr><tr><td style='padding-left:14px;' class='style3'>你的登录名为:<b style='color:#F3750F;'>" + userName + "</b></td></tr> <tr><td style='padding-left:14px;' class='style1'> 你的密码为:<b style='color:#F3750F;'>" + userPass + "</b></td></tr> <tr style=' font-size:15px; font-weight:bold;'><td><a href='"+"http://localhost:2556/WebSite/Register.aspx?Re="+ LoginService.GetStrUserRegist() + " * " + userName +"'>点此链接激活您都账号=></a></td></tr><tr><td>请在40分钟之内激活,逾期无效,抓紧时间哦~</td></tr><tr><td>点击进入考无忧官方网站:<a href='http://www.k51.com.cn'>http://www.k51.com.cn</a></td></tr><tr><td style='color:#999;font-size:12px;display:block;border-top:1px dotted #9F9F9F;padding-top:18px;padding-left:14px;' class='style4'>这只是一封系统自动发出的邮件,请不要直接回复。</td></tr></table></td></tr></table></td></tr></table></td></tr></table>"; //邮件正文 //mm.Attachments.Add(new Attachment(@"c:\d\1.doc", System.Net.Mime.MediaTypeNames.Application.Rtf)); //添加附件,第二个参数,表示附件的文件类型,可以不用指定 //可以添加多个附件 //mm.Attachments.Add(new Attachment(@"d:b.doc")); smtp.Send(mm); //发送邮件,如果不返回异常,则大功告成了。 } catch (Exception) { return false; } return true; }
发送激活邮件后,有一个页面,点击“跳转到邮箱”跳转用户注册邮箱首页。这个我觉得应该是在本地存了一个邮箱首页的库,根据用户的选择,判断对应邮箱提供方。
另外,把用户信息加密后Cookie存放在本地,可以实现“一周内保存”的功能。