在ASP.Net应用程序中发送电子邮件确认链接

时间:2013-12-23 06:49:23

标签: asp.net email

我想通过在我的asp.net 4.0应用程序中注册他们的电子邮件ID,密码和确认密码来允许人们。如何将确认链接发送到他们输入的电子邮件,并在其个人配置文件中显示个人资料强度?使用后端作为sql server 2010

2 个答案:

答案 0 :(得分:0)

您必须在链接中发送带有唯一确认ID的确认链接作为查询字符串参数。当用户点击该链接时,您可以验证该链接 -

  1. 链接是否已被使用?
  2. 链接是否有效确认号。
  3. 然后,如果它是有效链接,则允许用户确认有电子邮件ID。唯一的确认ID需要存储在给定电子邮件ID的数据库中。这样你就可以验证它。同样在同一个数据库表中,您可以使用其他字段来记录生成该ID并将电子邮件发送给用户的时间戳。

答案 1 :(得分:0)

<强>简介

随着.NET 2.0的推出,身份验证和授权作为Web应用程序的基本组成部分得到了极大的简化。可以使用不同的DBMS系统执行基本身份验证和授权。有许多使用Access数据库实现身份验证的示例。可以在使用Access数据库的ASP.NET 2.0身份验证一文中找到一个这样的示例。在本文中,该示例实现了最低限度以实现所需目标,即使用访问数据库进行身份验证和授权。但是,身份验证和授权只是用户管理系统的第一部分。用户管理的第二个基本部分是允许用户随意创建帐户。在这种情况下,用户可以在没有管理员干预的情况下注册并成为社区的成员。此外,用户应该能够提供联系信息(电子邮件),以便在必要时可以联系他/她。必须验证联系信息。本文重点介绍实现此目标的非常简单的方法。

<强>的CreateUserWizard

如前所述,.NET 2.0为快速有效地实现用户注册提供了必要的工具。感兴趣的组件是CreateUserWizard控件,可以在Login组件下找到。 CreateUserWizard组件提供预先格式化的组件集,为用户提供输入必要信息的机会。默认情况下,CreateUserWizard为用户提供输入名称,密码,电子邮件,安全问题和安全问题答案的选项。此外,CreateUserWizard为用户提供了重新输入密码以确认用户意图的功能。

在我们的示例中,我们将专注于实现用户注册和电子邮件确认的简约方法。因此,我们不会实施安全问题,而是专注于用户名,密码和电子邮件进行确认。本文是使用Access数据库继续ASP.NET 2.0授权,它重用了该文章中提供的角色和成员资格提供程序代码。在这里,我只介绍上述文章的补充内容。此外,还包括完整的源代码,演示可以在演示部分找到。

扩展角色和会员提供商

如前所述,我将专注于CreateUserWizard实现所需的其他实现。在提到的文章中解释了使用Access数据库在ASP.NET 2.0身份验证和授权中实现的方法。但是,有一些修改将在相关时间强调。

看看AccessMembershipProvider,我很快意识到必须实现多种方法才能正确使用CreateUserWizardcontrol。首先,我们需要能够消除安全问题选项。为了消除安全问题,成员资格提供者必须为成员资格提供者的RequiresQuestionAndAnswer属性返回false。此属性的实现类似于连接字符串属性的实现。我们只需添加bool类型的变量,从web配置文件中检索它的值。 Web配置文件必须包含requiresQuestionAndAnswer,如下所示:

<membership defaultProvider="AccessMembershipProvider">
<providers>
<clear/>
<add name="AccessMembershipProvider"
type="AccessProvider.AccessMembershipProvider"
connectionStringName="UsersDB"
requiresQuestionAndAnswer="false"/> 
</providers>
</membership>

设置在Initialize方法中解析如下:

public override void Initialize(string name, 
System.Collections.Specialized.NameValueCollection config)
{
base.Initialize(name, config); 
m_strDBConnection =
ConfigurationManager.ConnectionStrings[config["connectionStringName"]].ConnectionString; 
m_bRequiresQuestionAndAnswer = 
(config["requiresQuestionAndAnswer"].ToLower().CompareTo("true") == 0);
}

正如我们所看到的,上面的代码只是从web.config文件中提取设置并将其应用于适当的属性。 CreateUserWizard控件读取相同的属性并根据属性值显示安全问题。既然不必输入安全问题,我们可以查看用户输入数据并尝试创建用户时会发生什么。通过实验,我意识到(显然)调用了AccessMembershipProvider方法CreateUser。直观地,我得出结论,该方法负责将用户添加到数据库的代码。以下是方法实现:

public override MembershipUser CreateUser(string username,string password,string email,

string passwordQuestion, string passwordAnswer, 
bool isApproved, object providerUserKey, 
out MembershipCreateStatus status)
{
MembershipUser user = null; 
using (OleDbConnection conn = new OleDbConnection(m_strDBConnection))
{
try
{
OleDbCommand command = new OleDbCommand("INSERT INTO Users " + 
"(UUSERNAME, UPASSWORD, EMAIL, PROVIDER_KEY) "+
"VALUES (@Param1, @Param2, @Param3, @Param4)", 
conn); 
Guid guid = Guid.NewGuid();
command.Parameters.AddWithValue("@Param1", username);
command.Parameters.AddWithValue("@Param2", password);
command.Parameters.AddWithValue("@Param3", email);
command.Parameters.AddWithValue("@Param4", guid.ToString()); 
conn.Open(); 
command.ExecuteNonQuery(); 
string[] users = {username}; 
Roles.AddUsersToRole(users, "User"); 
conn.Close(); 
user = new MembershipUser("AccessMembershipProvider",
username, guid, email, null, null, false, false,
DateTime.Now, DateTime.Now, DateTime.Now, 
DateTime.Now, DateTime.Now); 
status = MembershipCreateStatus.Success;
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
status = MembershipCreateStatus.UserRejected;
}
}
return user;
}  

CreateUser方法只是将用户添加到数据库并返回使用CreateUserWizard中输入的信息填充的MembershipUser对象。我的第一个方法实现不包括使用角色提供程序将用户添加到“用户”组。但是,后来的调查显示,用户只是在没有分组的情况下添加。意识到用户必须在一个组中,我将以下实现添加到AccessRoleProvider代码:

public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
using (OleDbConnection conn = new OleDbConnection(m_strDBConnection))
{
try
{
for (int i = 0; i < usernames.Length; ++i)
{
OleDbCommand command = new OleDbCommand("INSERT INTO UsersInRoles "+
"(ROLE_NAME, UUSERNAME) "+
"VALUES (@Param1, @Param2)",
conn); 
command.Parameters.AddWithValue("@Param1", roleNames[i]);
command.Parameters.AddWithValue("@Param2", usernames[i]); 
conn.Open(); 
command.ExecuteNonQuery(); 
conn.Close();
}
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
}
} 

现在用户已添加到数据库并分配到适当的组,我们需要实现代码来确认用户信息,尤其是电子邮件。通过MSDN文档搜索,我发现CreateUserWizard提供了自动电子邮件通知的方法。但是,由于活动中缺乏信息,这种方法不合适。我们的构造将利用在创建用户时写入DB的GUID。仅当执行具有此类GUID的激活时才会激活用户。使用send email事件查找GUID是不切实际的,找到了更简单的解决方案,即CreateUserWizard组件的CreatedUser事件。

电子邮件通知

如前所述,只有在成功进行电子邮件确认后,用户才能使用该帐户。对于确认,用户应该收到一封电子邮件,其中包含将自动激活帐户的链接。帐户激活后,即可使用该帐户。以下是CreatedUser事件实现:

protected void CreateUserWizard1_CreatedUser(object sender, EventArgs e)
{
CreateUserWizard wizard = (CreateUserWizard)sender;
MembershipUser user = Membership.GetUser(wizard.UserName); 
if (user != null)
{
try
{
SmtpClient smtpClient = new SmtpClient("smtpServer");
smtpClient.UseDefaultCredentials = true;
smtpClient.Send("yourEmail", user.Email, "Account Conformation Email", 
"hst/Confirm.aspx?id="+user.ProviderUserKey.ToString());
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
}
} 

电子邮件通知的实施非常简单。这是因为.NET库提供了与任何SMTP服务器通信的非常简单的方法。重要的是要注意smtpClient.UseDefaultCredentials = true行。通过这种方式,smtpClient对象查找用于SMTP服务器设置的web.config,即用户名,密码和要使用的主机。 SmtpClient对象希望以下部分出现在web.config文件中:

<system.net>
<mailSettings>
<smtp>
<network
host="smtp.hst.com "
userName="username"
password="password" />
</smtp>
</mailSettings>
</system.net> 

设置不言自明。 smtpClient只需要使用主机名,用户名和密码。创建用户后,将引发CreatedUser事件并发送电子邮件。电子邮件的内容只是一个带有id参数的Confirm.aspx页面的链接。 id参数是专门为该用户分配的GUID。值得注意的是,也可以使用用户名,但GUID提供的安全性稍高。

CreatedUser事件正常运行所需的另一个扩展是AccessMembershipProvider对象能够根据用户名提供用户信息的功能。为了实现此类功能,AccessMembershipProvider包含将username作为参数并从数据库中读取用户信息的方法。以下是实施:

public override MembershipUser GetUser(string username, bool userIsOnline)
{
MembershipUser user = null; 
using (OleDbConnection conn = new OleDbConnection(m_strDBConnection))
{
try
{
/* Create command */
OleDbCommand command = 
new OleDbCommand("SELECT UUSERNAME, PROVIDER_KEY, EMAIL FROM Users " +
"WHERE UUSERNAME=@Param1", conn); 
command.Parameters.AddWithValue("@Param1", username); 
/* Open connection */
conn.Open(); 
/* Run query */
OleDbDataReader reader = command.ExecuteReader(); 
/* Check if we have something */
bool bResult = reader.HasRows; 
if (bResult)
{
reader.Read();
user = new MembershipUser("AccessMembershipProvider", reader.GetString(0), 
new Guid(reader.GetString(1)),
reader.GetString(2), "", "", true, false, 
DateTime.Now, DateTime.Now, DateTime.Now,
DateTime.Now, DateTime.Now);
}
/* Close connection */
conn.Close(); 
return user;
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
return user;
}
} 

再一次,实施是微不足道的。我们只需通过对用户表运行查询来查找有关具有指定用户名的用户的信息。

电子邮件确认

发送电子邮件后,用户会收到一封电子邮件,其中包含确认其注册和电子邮件的链接。该链接的格式为http://&#34; hst&#34; /Confirm.aspx?id = XXXXXXXXXXXXXXXXXX,其中XXXXXXXXXXXXXXXX是在CreateUser方法中确定的GUID。用户点击电子邮件后,浏览器会使用适当的参数加载Confirm.aspx页面。如怀疑,Confirm.aspx负责帐户激活。通过修改用户表中的ACTIVATED标志来执行帐户激活。以下是Confirm.aspx实施:

protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["id"] != null)
{
using (OleDbConnection conn = new OleDbConnection(
ConfigurationManager.ConnectionStrings["UsersDB"].ConnectionString))
{
try
{
OleDbCommand command = 
new OleDbCommand("UPDATE Users SET ACTIVATED=@Param1 "+
"WHERE PROVIDER_KEY=@Param2", conn);
command.Parameters.AddWithValue("@Param1", true);
command.Parameters.AddWithValue("@Param2", Request.QueryString["id"]); 
conn.Open(); 
command.ExecuteNonQuery(); 
conn.Close(); 
Response.Write("Your account has been activated. "+
"Please log in <a href='Default.aspx'>here</a>");
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
}
}
} 

实施是不言自明的。代码只是修改了具有指定GUID的用户的激活标志。

在这一点上,重要的是陈述一些明显的事实。必须修改AccessMembershipProvider的ValidateUser方法以考虑激活标志。换句话说,只有激活的用户才能被验证并因此登录。为了完整性,以下是实现:

public override bool ValidateUser(string username, string password)
{
using (OleDbConnection conn = new OleDbConnection(m_strDBConnection))
{
try
{
/* Create command */
OleDbCommand command = new OleDbCommand("SELECT UUSERNAME, UPASSWORD FROM Users " +
"WHERE UUSERNAME=@Param1 " +
"AND UPASSWORD=@Param2 " +
"AND ACTIVATED=@Param3",
conn); 
command.Parameters.AddWithValue("@Param1", username);
command.Parameters.AddWithValue("@Param2", password);
command.Parameters.AddWithValue("@Param3", true); 
/* Open connection */
conn.Open(); 
/* Run query */
OleDbDataReader reader = command.ExecuteReader(); 
/* Check if we have something */
bool bResult = reader.HasRows; 
/* Close connection */
conn.Close(); 
return bResult;
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
return false;
}
} 

访问数据库

使用的Access数据库是ASP.NET 2.0 Forms Authentication文章中使用的数据库的扩展版本,添加了GUID和ACTIVATED字段。 GUID存储在PROVIDER_KEY字段中。此外,由于与Access DB系统的冲突,必须重命名某些字段,如用户名和密码。

Source

Click here to demo