以编程方式将用户登录到asp.net成员资格和角色?

ink*_*thy 5 c# asp.net asp.net-membership asp.net-roles

我正在使用Asp.Net 4.0 Web应用程序,该应用程序使用Asp.Net的Membership和Roles功能.

在应用程序中,将有三个角色可以访问登录页面,一个角色没有.

它的工作方式如下.

后端用户(在三个特权角色之一中)创建用户.在代码中,这是以编程方式完成的,而不是使用"注册用户"页面.创建用户时,会将它们添加到非特权角色,为了清楚起见,该角色称为访问者角色.

然后,后端用户为新用户创建一个链接,其形式为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());
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我已经根据数据库表本身检查了用户名和密码的值,这一切都是正确的.我知道存储在aspnet表中的密码已经被盐析和散列,所以我正在检查我创建的临时表中的值以保存明文.这是正确的.此外,在上面的代码中,FormsAuthentication.SetAuthCookie方法要求输入用户名和密码 - 在这种情况下,用户名是电子邮件地址.在调试期间检查时,此信息也是正确的.

我应该指出,我们发送的链接几乎是一次性链接.每次更改与特定用户相关时,链接参数的值都将更改,旧链接将完全无用.他们将被重定向到的页面将保存与该特定用户直接相关的文档,而不包含其他文档.

但是,我们仍然需要Asp.Net Membership,Profiles和Roles框架的好处,因为"访问者"可能会向他们发送几个链接,随着时间的推移添加和更改不同的文档和文档版本.

谁能想到更好的方法?到目前为止,我已经在这里这里查看了大部分相关条目,但它们似乎都有点不完整.

编辑

我似乎至少部分地解决了这个问题,使用从这里接受的答案收集的信息

基本上,问题是我的web.config成员资格部分需要被告知要使用哪种哈希算法.目前,我不知道默认的是什么,如果有的话,但是添加

<membership hashAlgorithmType="SHA1">
Run Code Online (Sandbox Code Playgroud)

到web.config至少允许我登录添加上述行后创建的用户.下一步是让我理解为什么我无法让其他用户登录.

然而,我仍然得到Joe建议的ThreadAbortException,我现在忙于解决.

Joe*_*Joe 9

我不确定我是否完全理解您的问题,但是调用FormsAuthentication.SetAuthCookie将基本上以编程方式记录用户.

此外,在上面的代码中,FormsAuthentication.SetAuthCookie方法要求输入用户名和密码

不,SetAuthCookie需要用户名,但不需要密码.

在您的示例代码中,调用Response.Redirect将抛出一个ThreadAbortException,以便您的catch块将执行.也许这让你感到困惑.

回应评论:

基本上,我遇到的问题是用户似乎没有登录.FormsAuthenticate方法返回false

FormsAuthenticate上面的代码中没有方法.

话虽如此,我不明白你为什么要尝试Membership.ValidateUser在这种情况下验证user().我原本以为你想找到与查询字符串相关联的用户名,然后只需要打电话FormsAuthentication.SetAuthCookie给他登录.

  • @inkysmithy,您正在使用的`Response.Redirect`重载将立即通过抛出`ThreadAbortException`来终止当前请求.此行为意味着"Response.Redirect"之后的页面生命周期中的代码不会被执行.如果您不想要这种行为,请使用带有`endResponse`参数的`Response.Redirect`重载,您可以将其设置为`false`. (2认同)