我正在开发一个使用Asp.Net的Membership和Roles功能的Web应用程序。
在应用程序中,有三个角色可以访问登录页面,而另一个角色则无法访问。
它应该按照以下方式工作:
后端用户(属于三个特权角色之一)创建一个用户。在代码中,这是通过编程方式完成的,而不是使用注册用户页面。创建用户时,将其添加到非特权角色中,为了清晰起见,称为“访客”角色。
然后,后端用户为新用户创建一个链接,形式为https://www.example.com?link=cc82ae24-df47-4dbf-9440-1a6923945cf2。
当访问链接时,应用程序将定位与查询字符串相关联的用户,获取用户名和密码(适当地进行哈希和盐处理),并登录用户。
这是我不知道该怎么办了的地方。到目前为止,用户创建正常运行,基于查询字符串值的数据库查询正在发挥作用并返回相关信息,所有似乎都很顺利,除了实际的登录。似乎没有清晰的编程登录用户的方法,而不需要让用户自己登录,但我已明确被告知要避免这样做。
这是我的代码,“pers”对象是从数据库填充的类,当他们着陆链接的默认页面时:
现在,我已经检查了用户名和密码与数据库表本身的值,并且一切都是正确的。我理解aspnet表中存储的密码已被加盐和哈希,因此我正在检查我创建的临时表中的明文值。这是正确的。此外,在上面的代码中,FormsAuthentication.SetAuthCookie方法要求提供用户名和密码-在这种情况下,用户名是电子邮件地址。调试期间检查此信息也是正确的。
我应该指出,我们发送的链接基本上是一次性链接。每当针对特定用户进行更改时,链接参数的值都会更改,旧链接将变得完全无用。他们将被重定向到的页面将包含直接与该特定用户相关的文件,而不是其他任何人。
然而,我们仍然需要Asp.Net Membership、Profiles和Roles框架的好处,因为“访客”可能会收到几个链接,随着时间的推移,不同的文档和文档版本会被添加和更改。
将web.config文件进行更改,至少使我能够记录在上述行添加后创建的用户登录。下一步是让我了解为什么无法让其他用户登录。
然而,正如Joe所建议的那样,我仍然会遇到ThreadAbortException异常,并且现在我正在忙于解决它。
在应用程序中,有三个角色可以访问登录页面,而另一个角色则无法访问。
它应该按照以下方式工作:
后端用户(属于三个特权角色之一)创建一个用户。在代码中,这是通过编程方式完成的,而不是使用注册用户页面。创建用户时,将其添加到非特权角色中,为了清晰起见,称为“访客”角色。
然后,后端用户为新用户创建一个链接,形式为https://www.example.com?link=cc82ae24-df47-4dbf-9440-1a6923945cf2。
当访问链接时,应用程序将定位与查询字符串相关联的用户,获取用户名和密码(适当地进行哈希和盐处理),并登录用户。
这是我不知道该怎么办了的地方。到目前为止,用户创建正常运行,基于查询字符串值的数据库查询正在发挥作用并返回相关信息,所有似乎都很顺利,除了实际的登录。似乎没有清晰的编程登录用户的方法,而不需要让用户自己登录,但我已明确被告知要避免这样做。
这是我的代码,“pers”对象是从数据库填充的类,当他们着陆链接的默认页面时:
protected void LogUserIn(string p)
{
SqlConnection conn = UtilityMethods.GetConnection();
Guid par = Guid.Parse(p);
BioProspect pers= new BioProspect(conn);
pers.FillDetailsFromDb(par);
testlable.Text = pers.ToString();
Response.Cookies.Remove(FormsAuthentication.FormsCookieName);
try
{
if (Membership.ValidateUser(pers.Email, pers.Pword))
{
FormsAuthentication.SetAuthCookie(pers.Email, true);
Response.Redirect(Request.Url.Scheme + "://" + Request.Url.Host + "/About.aspx");
testlable.Text = "Logged in!";
}
else
{
throw new Exception("Something went wrong");
}
}
catch (Exception ex)
{
StringBuilder sb = new StringBuilder();
foreach (DictionaryEntry d in ex.Data)
{
sb.Append(d.Key.ToString());
sb.Append(": ");
sb.Append(d.Value.ToString());
sb.Append("\r\n");
}
AMessage(sb.ToString());
}
}
现在,我已经检查了用户名和密码与数据库表本身的值,并且一切都是正确的。我理解aspnet表中存储的密码已被加盐和哈希,因此我正在检查我创建的临时表中的明文值。这是正确的。此外,在上面的代码中,FormsAuthentication.SetAuthCookie方法要求提供用户名和密码-在这种情况下,用户名是电子邮件地址。调试期间检查此信息也是正确的。
我应该指出,我们发送的链接基本上是一次性链接。每当针对特定用户进行更改时,链接参数的值都会更改,旧链接将变得完全无用。他们将被重定向到的页面将包含直接与该特定用户相关的文件,而不是其他任何人。
然而,我们仍然需要Asp.Net Membership、Profiles和Roles框架的好处,因为“访客”可能会收到几个链接,随着时间的推移,不同的文档和文档版本会被添加和更改。
有没有更好的方法?我至今已经查看了大多数相关条目here和here,但它们似乎都有些不完整。
编辑
我似乎已经部分解决了这个问题,使用从被接受的答案中获得的信息here。
实际上,问题在于我的web.config成员身份验证部分需要告诉使用哪个哈希算法。目前,我不知道默认的哈希算法是什么,如果有的话,但是添加以下内容:
<membership hashAlgorithmType="SHA1">
将web.config文件进行更改,至少使我能够记录在上述行添加后创建的用户登录。下一步是让我了解为什么无法让其他用户登录。
然而,正如Joe所建议的那样,我仍然会遇到ThreadAbortException异常,并且现在我正在忙于解决它。
Membership.GetUser
并检查用户是否处于激活状态。但我不明白为什么你要进行身份验证,因为这需要你访问未加密的密码。如果Membership.ValidateUser
返回false,并且你的用户名有效,则说明你的密码不正确。 - JoeGetUser
检查状态,一旦所有细节都处理完毕,就对用户进行身份验证。我已经编辑了问题,以显示我现在似乎已经按照预期进行了身份验证。但是,我仍然对ThreadAbortException感到困惑 - a)您如何知道它会发生,b)请问我该如何停止它?我目前正在研究它。 - inksmithyResponse.Redirect
重载将通过抛出ThreadAbortException
立即终止当前请求。这种行为意味着在Response.Redirect
之后页面生命周期中的代码不会被执行。如果你不想要这种行为,可以使用带有endResponse
参数的Response.Redirect
重载,你可以将其设置为false
。 - Joe